diff --git a/OpenPGP-Keychain/build.gradle b/OpenPGP-Keychain/build.gradle index 0fffd1fd3..566559a00 100644 --- a/OpenPGP-Keychain/build.gradle +++ b/OpenPGP-Keychain/build.gradle @@ -24,8 +24,9 @@ dependencies { compile project(':libraries:ActionBarSherlock') compile project(':libraries:HtmlTextView') compile project(':libraries:StickyListHeaders:library') - compile project(':libraries:zxing') compile project(':libraries:AndroidBootstrap') + compile project(':libraries:zxing') + compile project(':libraries:zxing-android-integration') } android { diff --git a/OpenPGP-Keychain/libs/barcodescanner-android-integration-supportv4.jar b/OpenPGP-Keychain/libs/barcodescanner-android-integration-supportv4.jar deleted file mode 100644 index 4a7f1a39c..000000000 Binary files a/OpenPGP-Keychain/libs/barcodescanner-android-integration-supportv4.jar and /dev/null differ diff --git a/OpenPGP-Keychain/project.properties b/OpenPGP-Keychain/project.properties index 76caac668..96546d84f 100644 --- a/OpenPGP-Keychain/project.properties +++ b/OpenPGP-Keychain/project.properties @@ -14,3 +14,4 @@ android.library.reference.2=../libraries/HtmlTextView android.library.reference.3=../libraries/StickyListHeaders/library android.library.reference.4=../libraries/zxing android.library.reference.5=../libraries/AndroidBootstrap +android.library.reference.6=../libraries/zxing-android-integration diff --git a/OpenPGP-Keychain/res/layout/edit_key_activity.xml b/OpenPGP-Keychain/res/layout/edit_key_activity.xml index f8597b0df..351aec512 100644 --- a/OpenPGP-Keychain/res/layout/edit_key_activity.xml +++ b/OpenPGP-Keychain/res/layout/edit_key_activity.xml @@ -45,7 +45,7 @@ diff --git a/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml b/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml index f3c09a41d..5229e7cf5 100644 --- a/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml +++ b/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml @@ -10,7 +10,7 @@ android:layout_width="match_parent" android:layout_height="60dp" android:layout_margin="10dp" - android:text="@string/menu_import_from_qr_code" + android:text="@string/import_qr_scan_button" bootstrapbutton:bb_icon_left="fa-barcode" bootstrapbutton:bb_size="default" bootstrapbutton:bb_type="default" /> @@ -18,13 +18,19 @@ + android:layout_height="wrap_content" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:visibility="gone" /> + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:progress="0" + android:visibility="gone" /> \ No newline at end of file diff --git a/OpenPGP-Keychain/res/values/strings.xml b/OpenPGP-Keychain/res/values/strings.xml index 72709965a..746a13015 100644 --- a/OpenPGP-Keychain/res/values/strings.xml +++ b/OpenPGP-Keychain/res/values/strings.xml @@ -322,9 +322,16 @@ Import selected keys Import, Sign, and upload selected keys Import from Clipboard - Missing QR Codes: %1$s + + + Missing QR Code with ID %1$s + Missing QR Codes with IDs %1$s + + + Please start with QR Code with ID 1 QR Code malformed! Please try again! QR Code scanning finished! + Scan QR Code with \'Barcode Scanner\' OpenPGP: Decrypt File @@ -354,7 +361,7 @@ Go through all QR Codes using \'Next\', and scan them one by one. - QR Code %1$d of %2$d + QR Code with ID %1$d of %2$d Share with NFC diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 7d8f4154f..00a648355 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -76,6 +76,8 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi OnNavigationListener mOnNavigationListener; String[] mNavigationStrings; + Fragment mCurrentFragment; + BootstrapButton mImportButton; BootstrapButton mImportSignUploadButton; @@ -226,12 +228,12 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi } private void loadFragment(Class clss, Bundle args, String tag) { - Fragment fragment = Fragment.instantiate(this, clss.getName(), args); + mCurrentFragment = Fragment.instantiate(this, clss.getName(), args); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); // Replace whatever is in the fragment container with this fragment // and give the fragment a tag name equal to the string at the position selected - ft.replace(R.id.import_navigation_fragment, fragment, tag); + ft.replace(R.id.import_navigation_fragment, mCurrentFragment, tag); // Apply changes ft.commit(); } @@ -298,6 +300,15 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi // } // } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // required for qr code scanning + if (mCurrentFragment != null) { + mCurrentFragment.onActivityResult(requestCode, resultCode, data); + } + // super.onActivityResult(requestCode, resultCode, data); + } + /** * Import keys with mImportData */ diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java index f9ead3a94..bdedbec0a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java @@ -35,7 +35,7 @@ import android.widget.TextView; import android.widget.Toast; import com.beardedhen.androidbootstrap.BootstrapButton; -import com.google.zxing.integration.android.IntentIntegratorSupportV4; +import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; public class ImportKeysQrCodeFragment extends Fragment { @@ -45,7 +45,7 @@ public class ImportKeysQrCodeFragment extends Fragment { private TextView mText; private ProgressBar mProgress; - private String[] scannedContent; + private String[] mScannedContent; /** * Creates new instance of this fragment @@ -75,7 +75,7 @@ public class ImportKeysQrCodeFragment extends Fragment { @Override public void onClick(View v) { // scan using xzing's Barcode Scanner - new IntentIntegratorSupportV4(ImportKeysQrCodeFragment.this).initiateScan(); + new IntentIntegrator(getActivity()).initiateScan(); } }); @@ -92,9 +92,9 @@ public class ImportKeysQrCodeFragment extends Fragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { - case IntentIntegratorSupportV4.REQUEST_CODE: { - IntentResult scanResult = IntentIntegratorSupportV4.parseActivityResult(requestCode, - resultCode, data); + case IntentIntegrator.REQUEST_CODE: { + IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, + data); if (scanResult != null && scanResult.getFormatName() != null) { Log.d(Constants.TAG, scanResult.getContents()); @@ -117,36 +117,50 @@ public class ImportKeysQrCodeFragment extends Fragment { // first qr code -> setup if (counter == 0) { - scannedContent = new String[size]; + mScannedContent = new String[size]; mProgress.setMax(size); + mProgress.setVisibility(View.VISIBLE); + mText.setVisibility(View.VISIBLE); + } + + if (mScannedContent == null || counter > mScannedContent.length) { + Toast.makeText(getActivity(), R.string.import_qr_code_start_with_one, + Toast.LENGTH_LONG).show(); + return; } // save scanned content - scannedContent[counter] = content; + mScannedContent[counter] = content; // get missing numbers ArrayList missing = new ArrayList(); - for (int i = 0; i < scannedContent.length; i++) { - if (scannedContent[i] == null) { + for (int i = 0; i < mScannedContent.length; i++) { + if (mScannedContent[i] == null) { missing.add(i); } } // update progress and text - mProgress.setProgress(scannedContent.length - missing.size()); + int alreadyScanned = mScannedContent.length - missing.size(); + mProgress.setProgress(alreadyScanned); + String missingString = ""; for (int m : missing) { - if (!missingString.equals("")) + if (!missingString.equals("")) { missingString += ", "; + } missingString += String.valueOf(m + 1); } - mText.setText(getString(R.string.import_qr_code_missing, missingString)); + + String missingText = getResources().getQuantityString( + R.plurals.import_qr_code_missing, missing.size(), missingString); + mText.setText(missingText); // finished! if (missing.size() == 0) { mText.setText(R.string.import_qr_code_finished); String result = ""; - for (String in : scannedContent) { + for (String in : mScannedContent) { result += in; } mImportActivity.loadCallback(result.getBytes(), null); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ExpandableListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ExpandableListFragment.java deleted file mode 100644 index 54022342f..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ExpandableListFragment.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.ui.widget; - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.support.v4.app.Fragment; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnCreateContextMenuListener; -import android.view.ViewGroup; -import android.view.animation.AnimationUtils; -import android.widget.AdapterView; -import android.widget.ExpandableListAdapter; -import android.widget.ExpandableListView; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.ListAdapter; -import android.widget.ProgressBar; -import android.widget.TextView; - -/** - * @author Khoa Tran - * - * @see android.support.v4.app.ListFragment - * @see android.app.ExpandableListActivity - * - * ExpandableListFragment for Android < 3.0 - * - * from - * http://stackoverflow.com/questions/6051050/expandablelistfragment-with-loadermanager-for- - * compatibility-package - * - */ -public class ExpandableListFragment extends Fragment implements OnCreateContextMenuListener, - ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, - ExpandableListView.OnGroupExpandListener { - - static final int INTERNAL_EMPTY_ID = 0x00ff0001; - static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002; - static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; - - final private Handler mHandler = new Handler(); - - final private Runnable mRequestFocus = new Runnable() { - public void run() { - mExpandableList.focusableViewAvailable(mExpandableList); - } - }; - - final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { - public void onItemClick(AdapterView parent, View v, int position, long id) { - onListItemClick((ExpandableListView) parent, v, position, id); - } - }; - - ExpandableListAdapter mAdapter; - ExpandableListView mExpandableList; - boolean mFinishedStart = false; - View mEmptyView; - TextView mStandardEmptyView; - View mProgressContainer; - View mExpandableListContainer; - CharSequence mEmptyText; - boolean mExpandableListShown; - - public ExpandableListFragment() { - } - - /** - * Provide default implementation to return a simple list view. Subclasses can override to - * replace with their own layout. If doing so, the returned view hierarchy must have a - * ListView whose id is {@link android.R.id#list android.R.id.list} and can optionally have a - * sibling view id {@link android.R.id#empty android.R.id.empty} that is to be shown when the - * list is empty. - * - *

- * If you are overriding this method with your own custom content, consider including the - * standard layout {@link android.R.layout#list_content} in your layout file, so that you - * continue to retain all of the standard behavior of ListFragment. In particular, this is - * currently the only way to have the built-in indeterminant progress state be shown. - */ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final Context context = getActivity(); - - FrameLayout root = new FrameLayout(context); - - // ------------------------------------------------------------------ - - LinearLayout pframe = new LinearLayout(context); - pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID); - pframe.setOrientation(LinearLayout.VERTICAL); - pframe.setVisibility(View.GONE); - pframe.setGravity(Gravity.CENTER); - - ProgressBar progress = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge); - pframe.addView(progress, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - - root.addView(pframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - // ------------------------------------------------------------------ - - FrameLayout lframe = new FrameLayout(context); - lframe.setId(INTERNAL_LIST_CONTAINER_ID); - - TextView tv = new TextView(getActivity()); - tv.setId(INTERNAL_EMPTY_ID); - tv.setGravity(Gravity.CENTER); - lframe.addView(tv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - ExpandableListView lv = new ExpandableListView(getActivity()); - lv.setId(android.R.id.list); - lv.setDrawSelectorOnTop(false); - lframe.addView(lv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - root.addView(lframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - // ------------------------------------------------------------------ - - root.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - return root; - } - - /** - * Attach to list view once the view hierarchy has been created. - */ - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - ensureList(); - } - - /** - * Detach from list view. - */ - @Override - public void onDestroyView() { - mHandler.removeCallbacks(mRequestFocus); - mExpandableList = null; - mExpandableListShown = false; - mEmptyView = mProgressContainer = mExpandableListContainer = null; - mStandardEmptyView = null; - super.onDestroyView(); - } - - /** - * This method will be called when an item in the list is selected. Subclasses should override. - * Subclasses can call getListView().getItemAtPosition(position) if they need to access the data - * associated with the selected item. - * - * @param l - * The ListView where the click happened - * @param v - * The view that was clicked within the ListView - * @param position - * The position of the view in the list - * @param id - * The row id of the item that was clicked - */ - public void onListItemClick(ExpandableListView l, View v, int position, long id) { - } - - /** - * Provide the cursor for the list view. - */ - public void setListAdapter(ExpandableListAdapter adapter) { - boolean hadAdapter = mAdapter != null; - mAdapter = adapter; - if (mExpandableList != null) { - mExpandableList.setAdapter(adapter); - if (!mExpandableListShown && !hadAdapter) { - // The list was hidden, and previously didn't have an - // adapter. It is now time to show it. - setListShown(true, getView().getWindowToken() != null); - } - } - } - - /** - * Set the currently selected list item to the specified position with the adapter's data - * - * @param position - */ - public void setSelection(int position) { - ensureList(); - mExpandableList.setSelection(position); - } - - /** - * Get the position of the currently selected list item. - */ - public int getSelectedItemPosition() { - ensureList(); - return mExpandableList.getSelectedItemPosition(); - } - - /** - * Get the cursor row ID of the currently selected list item. - */ - public long getSelectedItemId() { - ensureList(); - return mExpandableList.getSelectedItemId(); - } - - /** - * Get the activity's list view widget. - */ - public ExpandableListView getListView() { - ensureList(); - return mExpandableList; - } - - /** - * The default content for a ListFragment has a TextView that can be shown when the list is - * empty. If you would like to have it shown, call this method to supply the text it should use. - */ - public void setEmptyText(CharSequence text) { - ensureList(); - if (mStandardEmptyView == null) { - throw new IllegalStateException("Can't be used with a custom content view"); - } - mStandardEmptyView.setText(text); - if (mEmptyText == null) { - mExpandableList.setEmptyView(mStandardEmptyView); - } - mEmptyText = text; - } - - /** - * Control whether the list is being displayed. You can make it not displayed if you are waiting - * for the initial data to show in it. During this time an indeterminant progress indicator will - * be shown instead. - * - *

- * Applications do not normally need to use this themselves. The default behavior of - * ListFragment is to start with the list not being shown, only showing it once an adapter is - * given with {@link #setListAdapter(ListAdapter)}. If the list at that point had not been - * shown, when it does get shown it will be do without the user ever seeing the hidden state. - * - * @param shown - * If true, the list view is shown; if false, the progress indicator. The initial - * value is true. - */ - public void setListShown(boolean shown) { - setListShown(shown, true); - } - - /** - * Like {@link #setListShown(boolean)}, but no animation is used when transitioning from the - * previous state. - */ - public void setListShownNoAnimation(boolean shown) { - setListShown(shown, false); - } - - /** - * Control whether the list is being displayed. You can make it not displayed if you are waiting - * for the initial data to show in it. During this time an indeterminant progress indicator will - * be shown instead. - * - * @param shown - * If true, the list view is shown; if false, the progress indicator. The initial - * value is true. - * @param animate - * If true, an animation will be used to transition to the new state. - */ - private void setListShown(boolean shown, boolean animate) { - ensureList(); - if (mProgressContainer == null) { - throw new IllegalStateException("Can't be used with a custom content view"); - } - if (mExpandableListShown == shown) { - return; - } - mExpandableListShown = shown; - if (shown) { - if (animate) { - mProgressContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), - android.R.anim.fade_out)); - mExpandableListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), - android.R.anim.fade_in)); - } else { - mProgressContainer.clearAnimation(); - mExpandableListContainer.clearAnimation(); - } - mProgressContainer.setVisibility(View.GONE); - mExpandableListContainer.setVisibility(View.VISIBLE); - } else { - if (animate) { - mProgressContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), - android.R.anim.fade_in)); - mExpandableListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), - android.R.anim.fade_out)); - } else { - mProgressContainer.clearAnimation(); - mExpandableListContainer.clearAnimation(); - } - mProgressContainer.setVisibility(View.VISIBLE); - mExpandableListContainer.setVisibility(View.GONE); - } - } - - /** - * Get the ListAdapter associated with this activity's ListView. - */ - public ExpandableListAdapter getListAdapter() { - return mAdapter; - } - - private void ensureList() { - if (mExpandableList != null) { - return; - } - View root = getView(); - if (root == null) { - throw new IllegalStateException("Content view not yet created"); - } - if (root instanceof ExpandableListView) { - mExpandableList = (ExpandableListView) root; - } else { - mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID); - if (mStandardEmptyView == null) { - mEmptyView = root.findViewById(android.R.id.empty); - } else { - mStandardEmptyView.setVisibility(View.GONE); - } - mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID); - mExpandableListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID); - View rawExpandableListView = root.findViewById(android.R.id.list); - if (!(rawExpandableListView instanceof ExpandableListView)) { - if (rawExpandableListView == null) { - throw new RuntimeException( - "Your content must have a ListView whose id attribute is " - + "'android.R.id.list'"); - } - throw new RuntimeException( - "Content has view with id attribute 'android.R.id.list' " - + "that is not a ListView class"); - } - mExpandableList = (ExpandableListView) rawExpandableListView; - if (mEmptyView != null) { - mExpandableList.setEmptyView(mEmptyView); - } else if (mEmptyText != null) { - mStandardEmptyView.setText(mEmptyText); - mExpandableList.setEmptyView(mStandardEmptyView); - } - } - mExpandableListShown = true; - mExpandableList.setOnItemClickListener(mOnClickListener); - if (mAdapter != null) { - ExpandableListAdapter adapter = mAdapter; - mAdapter = null; - setListAdapter(adapter); - } else { - // We are starting without an adapter, so assume we won't - // have our data right away and start with the progress indicator. - if (mProgressContainer != null) { - setListShown(false, false); - } - } - mHandler.post(mRequestFocus); - } - - /** - * Override this to populate the context menu when an item is long pressed. menuInfo will - * contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo} whose - * packedPosition is a packed position that should be used with - * {@link ExpandableListView#getPackedPositionType(long)} and the other similar methods. - *

- * {@inheritDoc} - */ - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - } - - /** - * Override this for receiving callbacks when a child has been clicked. - *

- * {@inheritDoc} - */ - public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, - int childPosition, long id) { - return false; - } - - /** - * Override this for receiving callbacks when a group has been collapsed. - */ - public void onGroupCollapse(int groupPosition) { - } - - /** - * Override this for receiving callbacks when a group has been expanded. - */ - public void onGroupExpand(int groupPosition) { - } - - // /** - // * Ensures the expandable list view has been created before Activity restores all - // * of the view states. - // * - // *@see Activity#onRestoreInstanceState(Bundle) - // */ - // @Override - // protected void onRestoreInstanceState(Bundle state) { - // ensureList(); - // super.onRestoreInstanceState(state); - // } - - /** - * Updates the screen state (current list and other views) when the content changes. - * - * @see Activity#onContentChanged() - */ - - public void onContentChanged() { - // super.onContentChanged(); - View emptyView = getView().findViewById(android.R.id.empty); - mExpandableList = (ExpandableListView) getView().findViewById(android.R.id.list); - if (mExpandableList == null) { - throw new RuntimeException( - "Your content must have a ExpandableListView whose id attribute is " - + "'android.R.id.list'"); - } - if (emptyView != null) { - mExpandableList.setEmptyView(emptyView); - } - mExpandableList.setOnChildClickListener(this); - mExpandableList.setOnGroupExpandListener(this); - mExpandableList.setOnGroupCollapseListener(this); - - if (mFinishedStart) { - setListAdapter(mAdapter); - } - mFinishedStart = true; - } - - /** - * Get the activity's expandable list view widget. This can be used to get the selection, set - * the selection, and many other useful functions. - * - * @see ExpandableListView - */ - public ExpandableListView getExpandableListView() { - ensureList(); - return mExpandableList; - } - - /** - * Get the ExpandableListAdapter associated with this activity's ExpandableListView. - */ - public ExpandableListAdapter getExpandableListAdapter() { - return mAdapter; - } - - /** - * Gets the ID of the currently selected group or child. - * - * @return The ID of the currently selected group or child. - */ - public long getSelectedId() { - return mExpandableList.getSelectedId(); - } - - /** - * Gets the position (in packed position representation) of the currently selected group or - * child. Use {@link ExpandableListView#getPackedPositionType}, - * {@link ExpandableListView#getPackedPositionGroup}, and - * {@link ExpandableListView#getPackedPositionChild} to unpack the returned packed position. - * - * @return A packed position representation containing the currently selected group or child's - * position and type. - */ - public long getSelectedPosition() { - return mExpandableList.getSelectedPosition(); - } - - /** - * Sets the selection to the specified child. If the child is in a collapsed group, the group - * will only be expanded and child subsequently selected if shouldExpandGroup is set to true, - * otherwise the method will return false. - * - * @param groupPosition - * The position of the group that contains the child. - * @param childPosition - * The position of the child within the group. - * @param shouldExpandGroup - * Whether the child's group should be expanded if it is collapsed. - * @return Whether the selection was successfully set on the child. - */ - public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) { - return mExpandableList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup); - } - - /** - * Sets the selection to the specified group. - * - * @param groupPosition - * The position of the group that should be selected. - */ - public void setSelectedGroup(int groupPosition) { - mExpandableList.setSelectedGroup(groupPosition); - } -} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java index b33dbe4c5..1f9605fb1 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -190,7 +190,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor keySizeAdapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); keySize.setAdapter(keySizeAdapter); - keySize.setSelection(2); // Default to 2048 for the key length + keySize.setSelection(3); // Default to 4096 for the key length dialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface di, int id) { diff --git a/README.md b/README.md index df2e72850..ee97fe0d1 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,8 @@ I am happy about every code contribution and appreciate your effort to help us d Android Studio is currently not supported or recommended! 1. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/ActionBarSherlock" -2. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/HtmlTextView" -3. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/StickyListHeaders/library" -4. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/zxing" -5. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/AndroidBootstrap" -6. File -> Import -> Android -> Existing Android Code Into Workspace, choose "OpenPGP-Keychain" -7. OpenPGP-Kechain can now be build +2. Repeat step 1 with "libraries/HtmlTextView", "libraries/StickyListHeaders/library", "libraries/AndroidBootstrap", "libraries/zxing", "libraries/zxing-android-integration", "OpenPGP-Keychain" +3. Now all required source files are available in Eclipse # Keychain API @@ -109,18 +105,16 @@ TODO # Libraries -## Build Barcode Scanner Integration +## ZXing Barcode Scanner Android Integration + +Classes can be found under "libraries/zxing-android-integration/". 1. Checkout their SVN (see http://code.google.com/p/zxing/source/checkout) -2. Change android-home variable in "build.properties" in the main directory to point to your Android SDK -3. Change directory to android-integration -4. Build using ``ant build`` -5. We use "android-integration-supportv4.jar" - -On error see: http://code.google.com/p/zxing/issues/detail?id=1207 +2. Copy all classes from their android-integration folder to our library folder ## ZXing +Classes can be found under "libraries/zxing/". ZXing classes were extracted from the ZXing library (http://code.google.com/p/zxing/). Only classes related to QR Code generation are utilized. diff --git a/libraries/zxing-android-integration/.gitignore b/libraries/zxing-android-integration/.gitignore new file mode 100644 index 000000000..71c11b159 --- /dev/null +++ b/libraries/zxing-android-integration/.gitignore @@ -0,0 +1,30 @@ +#Android specific +bin +gen +obj +libs/armeabi +lint.xml +local.properties +release.properties +ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* + +#Eclipse +.project +.classpath +.settings +.metadata + +#IntelliJ IDEA +.idea +*.iml diff --git a/libraries/zxing-android-integration/AndroidManifest.xml b/libraries/zxing-android-integration/AndroidManifest.xml new file mode 100644 index 000000000..c3a6ba464 --- /dev/null +++ b/libraries/zxing-android-integration/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/libraries/zxing-android-integration/build.gradle b/libraries/zxing-android-integration/build.gradle new file mode 100644 index 000000000..21050fc98 --- /dev/null +++ b/libraries/zxing-android-integration/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'android-library' + +android { + compileSdkVersion 19 + buildToolsVersion '19.0.0' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } + } +} diff --git a/libraries/zxing-android-integration/project.properties b/libraries/zxing-android-integration/project.properties new file mode 100644 index 000000000..91d2b0246 --- /dev/null +++ b/libraries/zxing-android-integration/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-19 +android.library=true diff --git a/libraries/zxing-android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java b/libraries/zxing-android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java new file mode 100644 index 000000000..4980e9e7e --- /dev/null +++ b/libraries/zxing-android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java @@ -0,0 +1,434 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.ActivityNotFoundException; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +/** + *

A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple + * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the + * project's source code.

+ * + *

Initiating a barcode scan

+ * + *

To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait + * for the result in your app.

+ * + *

It does require that the Barcode Scanner (or work-alike) application is installed. The + * {@link #initiateScan()} method will prompt the user to download the application, if needed.

+ * + *

There are a few steps to using this integration. First, your {@link Activity} must implement + * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:

+ * + *
{@code
+ * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ *   IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ *   if (scanResult != null) {
+ *     // handle scan result
+ *   }
+ *   // else continue with any other code you need in the method
+ *   ...
+ * }
+ * }
+ * + *

This is where you will handle a scan result.

+ * + *

Second, just call this in response to a user action somewhere to begin the scan process:

+ * + *
{@code
+ * IntentIntegrator integrator = new IntentIntegrator(yourActivity);
+ * integrator.initiateScan();
+ * }
+ * + *

Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the + * user was prompted to download the application. This lets the calling app potentially manage the dialog. + * In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()} + * method.

+ * + *

You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use + * {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and + * yes/no button labels can be changed.

+ * + *

Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used + * to invoke the scanner. This can be used to set additional options not directly exposed by this + * simplified API.

+ * + *

By default, this will only allow applications that are known to respond to this intent correctly + * do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}. + * For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.

+ * + *

Sharing text via barcode

+ * + *

To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.

+ * + *

Some code, particularly download integration, was contributed from the Anobiit application.

+ * + *

Enabling experimental barcode formats

+ * + *

Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as + * PDF417. Use {@link #initiateScan(java.util.Collection)} with + * a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such + * formats.

+ * + * @author Sean Owen + * @author Fred Lin + * @author Isaac Potoczny-Jones + * @author Brad Drehmer + * @author gcstang + */ +public class IntentIntegrator { + + public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits + private static final String TAG = IntentIntegrator.class.getSimpleName(); + + public static final String DEFAULT_TITLE = "Install Barcode Scanner?"; + public static final String DEFAULT_MESSAGE = + "This application requires Barcode Scanner. Would you like to install it?"; + public static final String DEFAULT_YES = "Yes"; + public static final String DEFAULT_NO = "No"; + + private static final String BS_PACKAGE = "com.google.zxing.client.android"; + private static final String BSPLUS_PACKAGE = "com.srowen.bs.android"; + + // supported barcode formats + public static final Collection PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14"); + public static final Collection ONE_D_CODE_TYPES = + list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128", + "ITF", "RSS_14", "RSS_EXPANDED"); + public static final Collection QR_CODE_TYPES = Collections.singleton("QR_CODE"); + public static final Collection DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX"); + + public static final Collection ALL_CODE_TYPES = null; + + public static final List TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE); + public static final List TARGET_ALL_KNOWN = list( + BSPLUS_PACKAGE, // Barcode Scanner+ + BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple + BS_PACKAGE // Barcode Scanner + // What else supports this intent? + ); + + private final Activity activity; + private String title; + private String message; + private String buttonYes; + private String buttonNo; + private List targetApplications; + private final Map moreExtras; + + public IntentIntegrator(Activity activity) { + this.activity = activity; + title = DEFAULT_TITLE; + message = DEFAULT_MESSAGE; + buttonYes = DEFAULT_YES; + buttonNo = DEFAULT_NO; + targetApplications = TARGET_ALL_KNOWN; + moreExtras = new HashMap(3); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setTitleByID(int titleID) { + title = activity.getString(titleID); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setMessageByID(int messageID) { + message = activity.getString(messageID); + } + + public String getButtonYes() { + return buttonYes; + } + + public void setButtonYes(String buttonYes) { + this.buttonYes = buttonYes; + } + + public void setButtonYesByID(int buttonYesID) { + buttonYes = activity.getString(buttonYesID); + } + + public String getButtonNo() { + return buttonNo; + } + + public void setButtonNo(String buttonNo) { + this.buttonNo = buttonNo; + } + + public void setButtonNoByID(int buttonNoID) { + buttonNo = activity.getString(buttonNoID); + } + + public Collection getTargetApplications() { + return targetApplications; + } + + public final void setTargetApplications(List targetApplications) { + if (targetApplications.isEmpty()) { + throw new IllegalArgumentException("No target applications"); + } + this.targetApplications = targetApplications; + } + + public void setSingleTargetApplication(String targetApplication) { + this.targetApplications = Collections.singletonList(targetApplication); + } + + public Map getMoreExtras() { + return moreExtras; + } + + public final void addExtra(String key, Object value) { + moreExtras.put(key, value); + } + + /** + * Initiates a scan for all known barcode types. + */ + public final AlertDialog initiateScan() { + return initiateScan(ALL_CODE_TYPES); + } + + /** + * Initiates a scan only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog initiateScan(Collection desiredBarcodeFormats) { + Intent intentScan = new Intent(BS_PACKAGE + ".SCAN"); + intentScan.addCategory(Intent.CATEGORY_DEFAULT); + + // check which types of codes to scan for + if (desiredBarcodeFormats != null) { + // set the desired barcode types + StringBuilder joinedByComma = new StringBuilder(); + for (String format : desiredBarcodeFormats) { + if (joinedByComma.length() > 0) { + joinedByComma.append(','); + } + joinedByComma.append(format); + } + intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString()); + } + + String targetAppPackage = findTargetAppPackage(intentScan); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intentScan.setPackage(targetAppPackage); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + attachMoreExtras(intentScan); + startActivityForResult(intentScan, REQUEST_CODE); + return null; + } + + /** + * Start an activity. This method is defined to allow different methods of activity starting for + * newer versions of Android and for compatibility library. + * + * @param intent Intent to start. + * @param code Request code for the activity + * @see android.app.Activity#startActivityForResult(Intent, int) + * @see android.app.Fragment#startActivityForResult(Intent, int) + */ + protected void startActivityForResult(Intent intent, int code) { + activity.startActivityForResult(intent, code); + } + + private String findTargetAppPackage(Intent intent) { + PackageManager pm = activity.getPackageManager(); + List availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (availableApps != null) { + for (String targetApp : targetApplications) { + if (contains(availableApps, targetApp)) { + return targetApp; + } + } + } + return null; + } + + private static boolean contains(Iterable availableApps, String targetApp) { + for (ResolveInfo availableApp : availableApps) { + String packageName = availableApp.activityInfo.packageName; + if (targetApp.equals(packageName)) { + return true; + } + } + return false; + } + + private AlertDialog showDownloadDialog() { + AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); + downloadDialog.setTitle(title); + downloadDialog.setMessage(message); + downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + String packageName; + if (targetApplications.contains(BS_PACKAGE)) { + // Prefer to suggest download of BS if it's anywhere in the list + packageName = BS_PACKAGE; + } else { + // Otherwise, first option: + packageName = targetApplications.get(0); + } + Uri uri = Uri.parse("market://details?id=" + packageName); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + try { + activity.startActivity(intent); + } catch (ActivityNotFoundException anfe) { + // Hmm, market is not installed + Log.w(TAG, "Google Play is not installed; cannot install " + packageName); + } + } + }); + downloadDialog.setNegativeButton(buttonNo, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) {} + }); + return downloadDialog.show(); + } + + + /** + *

Call this from your {@link Activity}'s + * {@link Activity#onActivityResult(int, int, Intent)} method.

+ * + * @return null if the event handled here was not related to this class, or + * else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning, + * the fields will be null. + */ + public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK) { + String contents = intent.getStringExtra("SCAN_RESULT"); + String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT"); + byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES"); + int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE); + Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation; + String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL"); + return new IntentResult(contents, + formatName, + rawBytes, + orientation, + errorCorrectionLevel); + } + return new IntentResult(); + } + return null; + } + + + /** + * Defaults to type "TEXT_TYPE". + * @see #shareText(CharSequence, CharSequence) + */ + public final AlertDialog shareText(CharSequence text) { + return shareText(text, "TEXT_TYPE"); + } + + /** + * Shares the given text by encoding it as a barcode, such that another user can + * scan the text off the screen of the device. + * + * @param text the text string to encode as a barcode + * @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants. + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog shareText(CharSequence text, CharSequence type) { + Intent intent = new Intent(); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setAction(BS_PACKAGE + ".ENCODE"); + intent.putExtra("ENCODE_TYPE", type); + intent.putExtra("ENCODE_DATA", text); + String targetAppPackage = findTargetAppPackage(intent); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intent.setPackage(targetAppPackage); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + attachMoreExtras(intent); + activity.startActivity(intent); + return null; + } + + private static List list(String... values) { + return Collections.unmodifiableList(Arrays.asList(values)); + } + + private void attachMoreExtras(Intent intent) { + for (Map.Entry entry : moreExtras.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + // Kind of hacky + if (value instanceof Integer) { + intent.putExtra(key, (Integer) value); + } else if (value instanceof Long) { + intent.putExtra(key, (Long) value); + } else if (value instanceof Boolean) { + intent.putExtra(key, (Boolean) value); + } else if (value instanceof Double) { + intent.putExtra(key, (Double) value); + } else if (value instanceof Float) { + intent.putExtra(key, (Float) value); + } else if (value instanceof Bundle) { + intent.putExtra(key, (Bundle) value); + } else { + intent.putExtra(key, value.toString()); + } + } + } + +} diff --git a/libraries/zxing-android-integration/src/com/google/zxing/integration/android/IntentResult.java b/libraries/zxing-android-integration/src/com/google/zxing/integration/android/IntentResult.java new file mode 100644 index 000000000..2469af92c --- /dev/null +++ b/libraries/zxing-android-integration/src/com/google/zxing/integration/android/IntentResult.java @@ -0,0 +1,95 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +/** + *

Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.

+ * + * @author Sean Owen + */ +public final class IntentResult { + + private final String contents; + private final String formatName; + private final byte[] rawBytes; + private final Integer orientation; + private final String errorCorrectionLevel; + + IntentResult() { + this(null, null, null, null, null); + } + + IntentResult(String contents, + String formatName, + byte[] rawBytes, + Integer orientation, + String errorCorrectionLevel) { + this.contents = contents; + this.formatName = formatName; + this.rawBytes = rawBytes; + this.orientation = orientation; + this.errorCorrectionLevel = errorCorrectionLevel; + } + + /** + * @return raw content of barcode + */ + public String getContents() { + return contents; + } + + /** + * @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names. + */ + public String getFormatName() { + return formatName; + } + + /** + * @return raw bytes of the barcode content, if applicable, or null otherwise + */ + public byte[] getRawBytes() { + return rawBytes; + } + + /** + * @return rotation of the image, in degrees, which resulted in a successful scan. May be null. + */ + public Integer getOrientation() { + return orientation; + } + + /** + * @return name of the error correction level used in the barcode, if applicable + */ + public String getErrorCorrectionLevel() { + return errorCorrectionLevel; + } + + @Override + public String toString() { + StringBuilder dialogText = new StringBuilder(100); + dialogText.append("Format: ").append(formatName).append('\n'); + dialogText.append("Contents: ").append(contents).append('\n'); + int rawBytesLength = rawBytes == null ? 0 : rawBytes.length; + dialogText.append("Raw bytes: (").append(rawBytesLength).append(" bytes)\n"); + dialogText.append("Orientation: ").append(orientation).append('\n'); + dialogText.append("EC level: ").append(errorCorrectionLevel).append('\n'); + return dialogText.toString(); + } + +} diff --git a/libraries/zxing/.gitignore b/libraries/zxing/.gitignore new file mode 100644 index 000000000..71c11b159 --- /dev/null +++ b/libraries/zxing/.gitignore @@ -0,0 +1,30 @@ +#Android specific +bin +gen +obj +libs/armeabi +lint.xml +local.properties +release.properties +ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* + +#Eclipse +.project +.classpath +.settings +.metadata + +#IntelliJ IDEA +.idea +*.iml diff --git a/settings.gradle b/settings.gradle index 5602503ee..021c54832 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,5 +2,6 @@ include ':OpenPGP-Keychain' include ':libraries:ActionBarSherlock' include ':libraries:HtmlTextView' include ':libraries:StickyListHeaders:library' -include ':libraries:zxing' include ':libraries:AndroidBootstrap' +include ':libraries:zxing' +include ':libraries:zxing-android-integration'