/*
* 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.encode;
import android.view.Display;
import android.view.MenuInflater;
import android.view.WindowManager;
import com.google.zxing.WriterException;
import com.google.zxing.client.android.Contents;
import com.google.zxing.client.android.FinishListener;
import com.google.zxing.client.android.Intents;
import com.google.zxing.client.android.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.zxing.FakeR;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* This class encodes data from an Intent into a QR code, and then displays it full screen so that
* another person can scan it with their device.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class EncodeActivity extends Activity {
private static final String TAG = EncodeActivity.class.getSimpleName();
private static final int MAX_BARCODE_FILENAME_LENGTH = 24;
private static final Pattern NOT_ALPHANUMERIC = Pattern.compile("[^A-Za-z0-9]");
private static final String USE_VCARD_KEY = "USE_VCARD";
private QRCodeEncoder qrCodeEncoder;
private static FakeR fakeR;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
fakeR = new FakeR(this);
Intent intent = getIntent();
if (intent == null) {
finish();
} else {
// String action = intent.getAction();
// if (Intents.Encode.ACTION.equals(action) || Intent.ACTION_SEND.equals(action)) {
setContentView(fakeR.getId("layout", "encode"));
// } else {
// finish();
// }
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(fakeR.getId("menu", "encode"), menu);
boolean useVcard = qrCodeEncoder != null && qrCodeEncoder.isUseVCard();
int encodeNameResource = useVcard ? fakeR.getId("string", "menu_encode_mecard") : fakeR.getId("string", "menu_encode_vcard");
MenuItem encodeItem = menu.findItem(fakeR.getId("id", "menu_encode"));
encodeItem.setTitle(encodeNameResource);
Intent intent = getIntent();
if (intent != null) {
String type = intent.getStringExtra(Intents.Encode.TYPE);
encodeItem.setVisible(Contents.Type.CONTACT.equals(type));
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == fakeR.getId("id", "menu_share")) {
share();
return true;
} else if (itemId == fakeR.getId("id", "menu_encode")) {
Intent intent = getIntent();
if (intent == null) {
return false;
}
intent.putExtra(USE_VCARD_KEY, !qrCodeEncoder.isUseVCard());
startActivity(intent);
finish();
return true;
} else {
return false;
}
}
private void share() {
QRCodeEncoder encoder = qrCodeEncoder;
if (encoder == null) { // Odd
Log.w(TAG, "No existing barcode to send?");
return;
}
String contents = encoder.getContents();
if (contents == null) {
Log.w(TAG, "No existing barcode to send?");
return;
}
Bitmap bitmap;
try {
bitmap = encoder.encodeAsBitmap();
} catch (WriterException we) {
Log.w(TAG, we);
return;
}
if (bitmap == null) {
return;
}
File bsRoot = new File(Environment.getExternalStorageDirectory(), "BarcodeScanner");
File barcodesRoot = new File(bsRoot, "Barcodes");
if (!barcodesRoot.exists() && !barcodesRoot.mkdirs()) {
Log.w(TAG, "Couldn't make dir " + barcodesRoot);
showErrorMessage(fakeR.getId("string", "msg_unmount_usb"));
return;
}
File barcodeFile = new File(barcodesRoot, makeBarcodeFileName(contents) + ".png");
barcodeFile.delete();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(barcodeFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 0, fos);
} catch (FileNotFoundException fnfe) {
Log.w(TAG, "Couldn't access file " + barcodeFile + " due to " + fnfe);
showErrorMessage(fakeR.getId("string", "msg_unmount_usb"));
return;
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
// do nothing
}
}
}
Intent intent = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_SUBJECT, getString(fakeR.getId("string", "app_name")) + " - " + encoder.getTitle());
intent.putExtra(Intent.EXTRA_TEXT, contents);
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + barcodeFile.getAbsolutePath()));
intent.setType("image/png");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(Intent.createChooser(intent, null));
}
private static CharSequence makeBarcodeFileName(CharSequence contents) {
String fileName = NOT_ALPHANUMERIC.matcher(contents).replaceAll("_");
if (fileName.length() > MAX_BARCODE_FILENAME_LENGTH) {
fileName = fileName.substring(0, MAX_BARCODE_FILENAME_LENGTH);
}
return fileName;
}
@Override
protected void onResume() {
super.onResume();
// This assumes the view is full screen, which is a good assumption
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
int smallerDimension = width < height ? width : height;
smallerDimension = smallerDimension * 7 / 8;
Intent intent = getIntent();
if (intent == null) {
return;
}
try {
boolean useVCard = intent.getBooleanExtra(USE_VCARD_KEY, false);
qrCodeEncoder = new QRCodeEncoder(this, intent, smallerDimension, useVCard);
Bitmap bitmap = qrCodeEncoder.encodeAsBitmap();
if (bitmap == null) {
Log.w(TAG, "Could not encode barcode");
showErrorMessage(fakeR.getId("string", "msg_encode_contents_failed"));
qrCodeEncoder = null;
return;
}
ImageView view = (ImageView) findViewById(fakeR.getId("id", "image_view"));
view.setImageBitmap(bitmap);
TextView contents = (TextView) findViewById(fakeR.getId("id", "contents_text_view"));
if (intent.getBooleanExtra(Intents.Encode.SHOW_CONTENTS, true)) {
contents.setText(qrCodeEncoder.getDisplayContents());
setTitle(qrCodeEncoder.getTitle());
} else {
contents.setText("");
setTitle("");
}
} catch (WriterException e) {
Log.w(TAG, "Could not encode barcode", e);
showErrorMessage(fakeR.getId("string", "msg_encode_contents_failed"));
qrCodeEncoder = null;
}
}
private void showErrorMessage(int message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
builder.setPositiveButton(fakeR.getId("string", "button_ok"), new FinishListener(this));
builder.setOnCancelListener(new FinishListener(this));
builder.show();
}
}