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:
dswitkin 2008-11-10 20:35:33 +00:00
parent ae46d12d21
commit f21c34ae16
13 changed files with 296 additions and 9 deletions

View file

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

50
android/res/layout/share.xml Executable file
View 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>

View file

@ -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>

View file

@ -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>

View file

@ -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());

View file

@ -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";
}
}

View file

@ -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);

View 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);
}
}
}

View file

@ -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) {

View file

@ -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>

View file

@ -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>

View file

@ -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);