QRCode Scan: implement embedded qr code scanner
This patch implements the embedded QR Code Scanner. Ring does not
need a third-party application to scan codes anymore.
It relies on a new dependency: com.journeyapps:zxing-android-embedded
Change-Id: I3097ed6302d8c3314cb665cfed6ab34e9dfb4ba0
Tuleap: #558
diff --git a/ring-android/app/src/main/AndroidManifest.xml b/ring-android/app/src/main/AndroidManifest.xml
index e02ceab..d3799c2 100644
--- a/ring-android/app/src/main/AndroidManifest.xml
+++ b/ring-android/app/src/main/AndroidManifest.xml
@@ -255,6 +255,12 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+ <activity android:name=".client.QRCodeScannerActivity"
+ android:screenOrientation="fullSensor"
+ android:stateNotNeeded="true"
+ android:theme="@style/zxing_CaptureTheme"
+ android:windowSoftInputMode="stateAlwaysHidden">
+ </activity>
<service
android:name=".service.LocalService"
diff --git a/ring-android/app/src/main/java/cx/ring/client/QRCodeScannerActivity.java b/ring-android/app/src/main/java/cx/ring/client/QRCodeScannerActivity.java
new file mode 100644
index 0000000..1196c92
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/client/QRCodeScannerActivity.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2016 Savoir-faire Linux Inc.
+ *
+ * Author: Romain Bertozzi <romain.bertozzi@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package cx.ring.client;
+
+import android.app.Fragment;
+
+import com.google.zxing.integration.android.IntentIntegrator;
+import com.journeyapps.barcodescanner.CaptureActivity;
+
+import cx.ring.R;
+
+public class QRCodeScannerActivity extends CaptureActivity {
+
+ /**
+ * Starts a QR Code scanner and passes the receiver to the engine to notify it with the result.
+ *
+ * @param receiver the Fragment to notify with the result of the scan.
+ */
+ public static void startQRCodeScanWithFragmentReceiver(Fragment receiver) {
+ if (null != receiver) {
+ IntentIntegrator integrator = IntentIntegrator.forFragment(receiver);
+ configureIntentIntegrator(integrator,
+ receiver.getString(R.string.scan_qr_account_message));
+ }
+ }
+
+ /**
+ * Configures the QR Code scanner with invariable parameters
+ *
+ * @param intentIntegrator the IntentIntegrator to configure
+ * @param promptString the text to display in the prompt of the QR Code scanner overlay
+ */
+ private static void configureIntentIntegrator(IntentIntegrator intentIntegrator,
+ String promptString) {
+ if (null == intentIntegrator) {
+ return;
+ }
+ intentIntegrator.setPrompt(promptString);
+ intentIntegrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES);
+ intentIntegrator.setCaptureActivity(QRCodeScannerActivity.class);
+ intentIntegrator.setBarcodeImageEnabled(true);
+ intentIntegrator.setOrientationLocked(false);
+ intentIntegrator.initiateScan();
+ }
+}
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
index 8aacb34..34723b8 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
@@ -63,6 +63,7 @@
import cx.ring.adapters.StarredContactsAdapter;
import cx.ring.client.ConversationActivity;
import cx.ring.client.HomeActivity;
+import cx.ring.client.QRCodeScannerActivity;
import cx.ring.loaders.ContactsLoader;
import cx.ring.loaders.LoaderConstants;
import cx.ring.model.CallContact;
@@ -72,8 +73,7 @@
public class SmartListFragment extends Fragment implements SearchView.OnQueryTextListener,
LoaderManager.LoaderCallbacks<ContactsLoader.Result>,
- HomeActivity.Refreshable
-{
+ HomeActivity.Refreshable {
private static final String TAG = SmartListFragment.class.getSimpleName();
private LocalService.Callbacks mCallbacks = LocalService.DUMMY_CALLBACKS;
@@ -135,8 +135,7 @@
if (mSmartListAdapter == null) {
bindService(getActivity(), service);
- }
- else {
+ } else {
mSmartListAdapter.updateDataset(service.getConversations());
}
@@ -177,7 +176,7 @@
public void onResume() {
Log.i(TAG, "onResume");
super.onResume();
- ((HomeActivity)getActivity()).setToolbarState(false, R.string.app_name);
+ ((HomeActivity) getActivity()).setToolbarState(false, R.string.app_name);
refresh();
}
@@ -205,6 +204,7 @@
setLoading(false);
return true;
}
+
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
dialpadMenuItem.setVisible(true);
@@ -257,8 +257,7 @@
mCallbacks.getService().clearHistory();
return true;
case R.id.menu_scan_qr:
- IntentIntegrator integrator = new IntentIntegrator(this);
- integrator.initiateScan();
+ QRCodeScannerActivity.startQRCodeScanWithFragmentReceiver(this);
default:
return false;
}
@@ -282,7 +281,7 @@
b.putString("filter", query);
getLoaderManager().restartLoader(LoaderConstants.CONTACT_LOADER, b, this);
newcontact.setVisibility(View.VISIBLE);
- ((TextView)newcontact.findViewById(R.id.display_name)).setText(/*getString(R.string.contact_call, query)*/query);
+ ((TextView) newcontact.findViewById(R.id.display_name)).setText(/*getString(R.string.contact_call, query)*/query);
CallContact contact = CallContact.buildUnknown(query);
newcontact.setTag(contact);
return true;
@@ -317,7 +316,7 @@
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final CallContact item = (CallContact) parent.getItemAtPosition(position);
- ((HomeActivity)getActivity()).onTextContact(item);
+ ((HomeActivity) getActivity()).onTextContact(item);
}
});
@@ -340,7 +339,7 @@
public void onClick(View v) {
CallContact c = (CallContact) newcontact.getTag();
if (c != null)
- ((HomeActivity)getActivity()).onCallContact(c);
+ ((HomeActivity) getActivity()).onCallContact(c);
}
});
@@ -366,7 +365,7 @@
service.get40dpContactCache(),
service.getThreadPool());
mListAdapter = new ContactsAdapter(ctx,
- (HomeActivity)getActivity(),
+ (HomeActivity) getActivity(),
service.get40dpContactCache(),
service.getThreadPool());
mGridAdapter = new StarredContactsAdapter(ctx);
@@ -569,12 +568,10 @@
private void initEmptyTextViewWhileLoading(boolean loading) {
if (null != this.contactList && this.contactList.getVisibility() == View.VISIBLE) {
this.mEmptyTextView.setText("");
- }
- else {
+ } else {
if (loading) {
this.mEmptyTextView.setText("");
- }
- else {
+ } else {
String emptyText = getResources().getQuantityString(R.plurals.home_conferences_title, 0, 0);
this.mEmptyTextView.setText(emptyText);
}
@@ -587,7 +584,8 @@
/**
* Handles the visibility of some menus to hide / show the overflow menu
- * @param menu the menu containing the menuitems we need to access
+ *
+ * @param menu the menu containing the menuitems we need to access
* @param visible true to display the overflow menu, false otherwise
*/
private void setOverflowMenuVisible(final Menu menu, boolean visible) {
diff --git a/ring-android/app/src/main/res/values/strings.xml b/ring-android/app/src/main/res/values/strings.xml
index 02091aa..2baebab 100644
--- a/ring-android/app/src/main/res/values/strings.xml
+++ b/ring-android/app/src/main/res/values/strings.xml
@@ -158,4 +158,7 @@
<!-- Write call log permission -->
<string name="permission_dialog_write_call_log_message">Ring needs the "Write call log" permission to enable this feature. Please grant it.</string>
+ <!-- QRCode Scan -->
+ <string name="scan_qr_account_message">Scan the QR Code of the account you want to add.</string>
+
</resources>