mirror of
https://github.com/zxing/zxing.git
synced 2024-11-09 20:44:03 -08:00
First pass at adding a UI for sharing data via QR Codes. There's now a Share button in the main capture menu which leads to a choice of contacts, bookmarks, and clipboard contents, which will be encoded and shown full screen. Launching the bookmarks picker currently crashes with a permission problem, which I'm investigating.
git-svn-id: https://zxing.googlecode.com/svn/trunk@681 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
ae46d12d21
commit
f21c34ae16
|
@ -70,9 +70,18 @@ versionName is 2.31, 2.4, or 3.0. -->
|
|||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="ShareActivity"
|
||||
android:label="@string/share_name"
|
||||
android:screenOrientation="user">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.zxing.client.android.SHARE"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_BROWSER_HISTORY_BOOKMARKS"/>
|
||||
</manifest>
|
||||
|
|
BIN
android/res/drawable/share_barcode.png
Executable file
BIN
android/res/drawable/share_barcode.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
50
android/res/layout/share.xml
Executable file
50
android/res/layout/share.xml
Executable file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/encode_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@color/share_view"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="8px">
|
||||
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left"
|
||||
android:textColor="@color/share_text"
|
||||
android:textSize="18.0sp"
|
||||
android:text="@string/msg_share_explanation"
|
||||
android:paddingBottom="16px"/>
|
||||
|
||||
<Button android:id="@+id/contact_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_share_contact"/>
|
||||
|
||||
<Button android:id="@+id/bookmark_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_share_bookmark"/>
|
||||
|
||||
<Button android:id="@+id/clipboard_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_share_clipboard"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -28,6 +28,8 @@
|
|||
<color name="sbc_layout_view">#ffffffff</color>
|
||||
<color name="sbc_page_number_text">#ff000000</color>
|
||||
<color name="sbc_snippet_text">#ff4b4b4b</color>
|
||||
<color name="share_text">#ff000000</color>
|
||||
<color name="share_view">#ffffffff</color>
|
||||
<color name="status_view">#50000000</color>
|
||||
<color name="status_text">#ffffffff</color>
|
||||
<color name="transparent">#00000000</color>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<string name="button_add_contact">Add contact</string>
|
||||
<string name="button_book_search">Open Book Search</string>
|
||||
<string name="button_cancel">Cancel</string>
|
||||
<string name="button_clipboard_empty">Clipboard empty</string>
|
||||
<string name="button_dial">Dial number</string>
|
||||
<string name="button_email">Send email</string>
|
||||
<string name="button_get_directions">Get directions</string>
|
||||
|
@ -29,8 +30,11 @@
|
|||
<string name="button_open_browser">Open browser</string>
|
||||
<string name="button_product_search">Open Product Search</string>
|
||||
<string name="button_search_book_contents">Search book contents</string>
|
||||
<string name="button_share_bookmark">Share bookmark</string>
|
||||
<string name="button_share_by_email">Share via email</string>
|
||||
<string name="button_share_by_sms">Share via SMS</string>
|
||||
<string name="button_share_clipboard">Share clipboard</string>
|
||||
<string name="button_share_contact">Share contact</string>
|
||||
<string name="button_show_map">Show map</string>
|
||||
<string name="button_sms">Send SMS</string>
|
||||
<string name="button_web_search">Web search</string>
|
||||
|
@ -45,6 +49,7 @@
|
|||
<string name="menu_about">About</string>
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="menu_share">Share</string>
|
||||
|
||||
<string name="msg_about">Based on the open source ZXing Barcode Library</string>
|
||||
<string name="msg_default_contents">Contents</string>
|
||||
|
@ -66,8 +71,10 @@
|
|||
<string name="msg_sbc_page">Page</string>
|
||||
<string name="msg_sbc_snippet_unavailable">Snippet not available</string>
|
||||
<string name="msg_sbc_unknown_page">Unknown page</string>
|
||||
<string name="msg_searching_book">Searching book\u2026</string>
|
||||
<string name="msg_share_barcode">Here\'s the contents of a barcode I scanned</string>
|
||||
<string name="msg_sbc_searching_book">Searching book\u2026</string>
|
||||
<string name="msg_share_explanation">You can share data with a friend by displaying a barcode on
|
||||
your screen, and letting them scan it with their phone.</string>
|
||||
<string name="msg_share_subject_line">Here\'s the contents of a barcode I scanned</string>
|
||||
|
||||
<string name="preferences_decode_1D_title">Decode 1D barcodes</string>
|
||||
<string name="preferences_decode_QR_title">Decode QR Codes</string>
|
||||
|
@ -88,6 +95,7 @@
|
|||
<string name="result_uri">Found URL</string>
|
||||
|
||||
<string name="sbc_name">Google Book Search</string>
|
||||
<string name="share_name">Share via barcode</string>
|
||||
|
||||
<string name="title_about">About Barcode Scanner</string>
|
||||
<string name="title_help">Help</string>
|
||||
|
|
|
@ -51,9 +51,9 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.client.android.result.ResultButtonListener;
|
||||
import com.google.zxing.client.android.result.ResultHandler;
|
||||
import com.google.zxing.client.android.result.ResultHandlerFactory;
|
||||
import com.google.zxing.client.android.result.ResultButtonListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -63,9 +63,10 @@ import java.io.IOException;
|
|||
*/
|
||||
public final class BarcodesCaptureActivity extends Activity implements SurfaceHolder.Callback {
|
||||
|
||||
private static final int SETTINGS_ID = Menu.FIRST;
|
||||
private static final int HELP_ID = Menu.FIRST + 1;
|
||||
private static final int ABOUT_ID = Menu.FIRST + 2;
|
||||
private static final int SHARE_ID = Menu.FIRST;
|
||||
private static final int SETTINGS_ID = Menu.FIRST + 1;
|
||||
private static final int HELP_ID = Menu.FIRST + 2;
|
||||
private static final int ABOUT_ID = Menu.FIRST + 3;
|
||||
|
||||
private static final int MAX_RESULT_IMAGE_SIZE = 150;
|
||||
private static final int INTENT_RESULT_DURATION = 1500;
|
||||
|
@ -167,6 +168,7 @@ public final class BarcodesCaptureActivity extends Activity implements SurfaceHo
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, SHARE_ID, 0, R.string.menu_share).setIcon(R.drawable.share_barcode);
|
||||
menu.add(0, SETTINGS_ID, 0, R.string.menu_settings)
|
||||
.setIcon(android.R.drawable.ic_menu_preferences);
|
||||
menu.add(0, HELP_ID, 0, R.string.menu_help)
|
||||
|
@ -179,6 +181,12 @@ public final class BarcodesCaptureActivity extends Activity implements SurfaceHo
|
|||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case SHARE_ID: {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setClassName(this, ShareActivity.class.getName());
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
case SETTINGS_ID: {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setClassName(this, BarcodesPreferenceActivity.class.getName());
|
||||
|
|
|
@ -109,4 +109,12 @@ public final class Intents {
|
|||
public static final String QUERY = "QUERY";
|
||||
}
|
||||
|
||||
public static final class Share {
|
||||
/**
|
||||
* Give the user a choice of items to encode as a barcode, then render it as a QR Code and
|
||||
* display onscreen for a friend to scan with their phone.
|
||||
*/
|
||||
public static final String ACTION = "com.google.zxing.client.android.SHARE";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ public class SearchBookContentsActivity extends Activity {
|
|||
if (query != null && query.length() > 0) {
|
||||
mNetworkThread = new NetworkThread(mISBN, query, mHandler);
|
||||
mNetworkThread.start();
|
||||
mHeaderView.setText(R.string.msg_searching_book);
|
||||
mHeaderView.setText(R.string.msg_sbc_searching_book);
|
||||
mResultListView.setAdapter(null);
|
||||
mQueryTextView.setEnabled(false);
|
||||
mQueryButton.setEnabled(false);
|
||||
|
|
188
android/src/com/google/zxing/client/android/ShareActivity.java
Executable file
188
android/src/com/google/zxing/client/android/ShareActivity.java
Executable file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.client.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Contacts;
|
||||
import android.text.ClipboardManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
public final class ShareActivity extends Activity {
|
||||
|
||||
private static final int PICK_BOOKMARK = 0;
|
||||
private static final int PICK_CONTACT = 1;
|
||||
|
||||
private static final int METHODS_ID_COLUMN = 0;
|
||||
private static final int METHODS_KIND_COLUMN = 1;
|
||||
private static final int METHODS_DATA_COLUMN = 2;
|
||||
|
||||
private static final String[] METHODS_PROJECTION = new String[] {
|
||||
Contacts.People.ContactMethods._ID, // 0
|
||||
Contacts.People.ContactMethods.KIND, // 1
|
||||
Contacts.People.ContactMethods.DATA, // 2
|
||||
};
|
||||
|
||||
private Button mContactButton;
|
||||
private Button mBookmarkButton;
|
||||
private Button mClipboardButton;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.share);
|
||||
|
||||
mContactButton = (Button) findViewById(R.id.contact_button);
|
||||
mContactButton.setOnClickListener(mContactListener);
|
||||
mBookmarkButton = (Button) findViewById(R.id.bookmark_button);
|
||||
mBookmarkButton.setOnClickListener(mBookmarkListener);
|
||||
mClipboardButton = (Button) findViewById(R.id.clipboard_button);
|
||||
mClipboardButton.setOnClickListener(mClipboardListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (clipboard.hasText()) {
|
||||
mClipboardButton.setEnabled(true);
|
||||
mClipboardButton.setText(R.string.button_share_clipboard);
|
||||
} else {
|
||||
mClipboardButton.setEnabled(false);
|
||||
mClipboardButton.setText(R.string.button_clipboard_empty);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private final Button.OnClickListener mContactListener = new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
startActivityForResult(new Intent(Intent.ACTION_PICK, Contacts.People.CONTENT_URI),
|
||||
PICK_CONTACT);
|
||||
}
|
||||
};
|
||||
|
||||
private final Button.OnClickListener mBookmarkListener = new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
// FIXME: Not working yet
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName("com.android.browser",
|
||||
"com.android.browser.BrowserBookmarksPage"));
|
||||
startActivityForResult(intent, PICK_BOOKMARK);
|
||||
}
|
||||
};
|
||||
|
||||
private final Button.OnClickListener mClipboardListener = new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
// Should always be true, because we grey out the clipboard button in onResume() if it's empty
|
||||
if (clipboard.hasText()) {
|
||||
Intent intent = new Intent(Intents.Encode.ACTION);
|
||||
intent.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT);
|
||||
intent.putExtra(Intents.Encode.DATA, clipboard.getText());
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
switch (requestCode) {
|
||||
case PICK_BOOKMARK:
|
||||
// FIXME: Implement
|
||||
Log.v("BOOKMARK", intent.toString());
|
||||
break;
|
||||
case PICK_CONTACT:
|
||||
// Data field is content://contacts/people/984
|
||||
showContactAsBarcode(intent.getData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a contact Uri and does the necessary database lookups to retrieve that person's info,
|
||||
* then sends an Encode intent to render it as a QR Code.
|
||||
*
|
||||
* @param contactUri A Uri of the form content://contacts/people/17
|
||||
*/
|
||||
private void showContactAsBarcode(Uri contactUri) {
|
||||
ContentResolver resolver = getContentResolver();
|
||||
Cursor contactCursor = resolver.query(contactUri, null, null, null, null);
|
||||
Bundle bundle = new Bundle();
|
||||
if (contactCursor != null && contactCursor.moveToFirst()) {
|
||||
int nameColumn = contactCursor.getColumnIndex(Contacts.People.NAME);
|
||||
String name = contactCursor.getString(nameColumn);
|
||||
if (name == null || name.length() == 0) {
|
||||
// TODO: Show error
|
||||
return;
|
||||
}
|
||||
bundle.putString(Contacts.Intents.Insert.NAME, name);
|
||||
|
||||
int phoneColumn = contactCursor.getColumnIndex(Contacts.People.NUMBER);
|
||||
bundle.putString(Contacts.Intents.Insert.PHONE, contactCursor.getString(phoneColumn));
|
||||
contactCursor.close();
|
||||
|
||||
Uri methodsUri = Uri.withAppendedPath(contactUri,
|
||||
Contacts.People.ContactMethods.CONTENT_DIRECTORY);
|
||||
Cursor methodsCursor = resolver.query(methodsUri, METHODS_PROJECTION, null, null, null);
|
||||
boolean foundEmail = false;
|
||||
boolean foundPostal = false;
|
||||
if (methodsCursor != null) {
|
||||
while (methodsCursor.moveToNext()) {
|
||||
final int kind = methodsCursor.getInt(METHODS_KIND_COLUMN);
|
||||
final String data = methodsCursor.getString(METHODS_DATA_COLUMN);
|
||||
switch (kind) {
|
||||
case Contacts.KIND_EMAIL:
|
||||
if (!foundEmail) {
|
||||
// Use the first address encountered, since we can't encode multiple addresses
|
||||
bundle.putString(Contacts.Intents.Insert.EMAIL, data);
|
||||
foundEmail = true;
|
||||
}
|
||||
break;
|
||||
case Contacts.KIND_POSTAL:
|
||||
if (!foundPostal) {
|
||||
bundle.putString(Contacts.Intents.Insert.POSTAL, data);
|
||||
foundPostal = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
methodsCursor.close();
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intents.Encode.ACTION);
|
||||
intent.putExtra(Intents.Encode.TYPE, Contents.Type.CONTACT);
|
||||
intent.putExtra(Intents.Encode.DATA, bundle);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -148,7 +148,7 @@ public abstract class ResultHandler {
|
|||
}
|
||||
|
||||
public void shareByEmail(String contents) {
|
||||
sendEmailFromUri("mailto:", mActivity.getString(R.string.msg_share_barcode), contents);
|
||||
sendEmailFromUri("mailto:", mActivity.getString(R.string.msg_share_subject_line), contents);
|
||||
}
|
||||
|
||||
public void sendEmail(String address, String subject, String body) {
|
||||
|
@ -163,7 +163,7 @@ public abstract class ResultHandler {
|
|||
}
|
||||
|
||||
public void shareBySMS(String contents) {
|
||||
sendSMSFromUri("smsto:", mActivity.getString(R.string.msg_share_barcode) + ":\n" + contents);
|
||||
sendSMSFromUri("smsto:", mActivity.getString(R.string.msg_share_subject_line) + ":\n" + contents);
|
||||
}
|
||||
|
||||
public void sendSMS(String phoneNumber, String body) {
|
||||
|
|
|
@ -84,5 +84,9 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/encode_bad_data"/>
|
||||
<Button android:id="@+id/share_via_barcode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/share_via_barcode"/>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<string name="status_message">Press the shutter button to save images to the SD card for testing purposes. Press DPAD_CENTER to trigger autofocus.</string>
|
||||
<string name="save_succeeded">Save succeeded</string>
|
||||
<string name="save_failed">Save failed - is the SD card installed?</string>
|
||||
<string name="share_via_barcode">Share via barcode</string>
|
||||
|
||||
<string name="benchmark_name">ZXing Benchmark</string>
|
||||
<string name="benchmark_help">Place images in /sdcard/zxingbenchmark, then check \"adb logcat\" for results. Turn on Airplane Mode first for more reliable results.</string>
|
||||
|
|
|
@ -70,6 +70,9 @@ public class ZXingTestActivity extends Activity {
|
|||
|
||||
Button encode_bad_data = (Button) findViewById(R.id.encode_bad_data);
|
||||
encode_bad_data.setOnClickListener(mEncodeBadData);
|
||||
|
||||
Button share_via_barcode = (Button) findViewById(R.id.share_via_barcode);
|
||||
share_via_barcode.setOnClickListener(mShareViaBarcode);
|
||||
}
|
||||
|
||||
public Button.OnClickListener mTestCamera = new Button.OnClickListener() {
|
||||
|
@ -183,6 +186,12 @@ public class ZXingTestActivity extends Activity {
|
|||
}
|
||||
};
|
||||
|
||||
public Button.OnClickListener mShareViaBarcode = new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent("com.google.zxing.client.android.SHARE"));
|
||||
}
|
||||
};
|
||||
|
||||
private void showDialog(int title, String message) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(title);
|
||||
|
|
Loading…
Reference in a new issue