diff options
Diffstat (limited to 'quickReader/src/org/lineageos/quickreader/ScannerActivity.java')
-rw-r--r-- | quickReader/src/org/lineageos/quickreader/ScannerActivity.java | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/quickReader/src/org/lineageos/quickreader/ScannerActivity.java b/quickReader/src/org/lineageos/quickreader/ScannerActivity.java new file mode 100644 index 000000000..fb583a24a --- /dev/null +++ b/quickReader/src/org/lineageos/quickreader/ScannerActivity.java @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2017 The LineageOS 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.lineageos.quickreader; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; +import android.util.Patterns; +import android.webkit.URLUtil; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.google.zxing.Result; + +import java.util.concurrent.ExecutionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.android.camera.CameraActivity; +import me.dm7.barcodescanner.zxing.ZXingScannerView; + +import org.codeaurora.snapcam.R; + +public class ScannerActivity extends Activity implements ZXingScannerView.ResultHandler { + private static final String TAG = "QuickReader"; + private static final int REQUEST_CAMERA = 391; + public static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile( + "(?i)" + // switch on case insensitive matching + "(" + // begin group for schema + "(?:http|https|file|chrome)://" + + "|(?:inline|data|about|javascript):" + + ")" + + "(.*)" + ); + + private static ScannerIntentHelper sHelper; + + private AnalyzeTask task; + + private ZXingScannerView mScanView; + private FrameLayout mIdentifyLayout; + private ImageView mIdentifyIcon; + private ImageView mFlashIcon; + + private boolean allowReading = true; + + @Override + protected void onCreate(Bundle savedInstance) { + super.onCreate(savedInstance); + + setContentView(R.layout.activity_scanner); + + mScanView = (ZXingScannerView) findViewById(R.id.scanner_view); + mIdentifyLayout = (FrameLayout) findViewById(R.id.identify_layout); + mIdentifyIcon = (ImageView) findViewById(R.id.identify_icon); + mFlashIcon = (ImageView) findViewById(R.id.action_flash); + ImageView closeIcon = (ImageView) findViewById(R.id.action_close); + + mIdentifyLayout.setOnClickListener(v -> sHelper.run(this)); + mFlashIcon.setOnClickListener(v -> toggleFlash()); + closeIcon.setOnClickListener(v -> finish()); + + if (!hasCameraPermission()) { + requestPermission(); + } + + sHelper = ScannerIntentHelper.getInstance(); + task = new AnalyzeTask(); + } + + @Override + public void onResume() { + super.onResume(); + + mScanView.setResultHandler(this); + mScanView.startCamera(); + } + + @Override + public void onPause() { + super.onPause(); + + try { + if (mScanView.getFlash()) { + mScanView.setFlash(false); + mFlashIcon.setImageResource(R.drawable.ic_flash_off); + } + } catch (Exception ignored) { + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + + mScanView.stopCamera(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults) { + if (requestCode != REQUEST_CAMERA || permissions.length == 0 || grantResults.length == 0) { + return; + } + + if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { + if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { + showRationaleErrorDialog(); + } else { + showFatalErrorDialog(); + } + } + } + + @Override + public void handleResult(Result rawResult) { + mScanView.resumeCameraPreview(this); + + if (!allowReading) { + return; + } + + if (task.getStatus() == AsyncTask.Status.RUNNING) { + return; + } + + allowReading = false; + task = new AnalyzeTask(); + task.execute(rawResult.getText()); + + try { + int result = task.get(); + postAnalyze(result); + allowReading = true; + } catch (InterruptedException | ExecutionException e) { + Log.e(TAG, e.getMessage()); + } + } + + private boolean hasCameraPermission() { + return checkSelfPermission(Manifest.permission.CAMERA) == + PackageManager.PERMISSION_GRANTED; + } + + private void requestPermission() { + requestPermissions(new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA); + } + + private void openSettings() { + Uri uri = Uri.fromParts("package", getPackageName(), null); + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri); + startActivity(intent); + } + + private void showRationaleErrorDialog() { + new AlertDialog.Builder(this) + .setTitle(R.string.quick_reader_permission_error_title) + .setMessage(R.string.quick_reader_permission_rationale_message) + .setPositiveButton(R.string.quick_reader_permission_rationale_positive, + (dialog, i) -> requestPermission()) + .setNegativeButton(R.string.quick_reader_action_dismiss, + (dialog, i) -> finish()) + .show(); + } + + private void showFatalErrorDialog() { + new AlertDialog.Builder(this) + .setTitle(R.string.quick_reader_permission_error_title) + .setMessage(R.string.quick_reader_permission_fatal_message) + .setPositiveButton(R.string.quick_reader_permission_fatal_positive, + (dialog, i) -> openSettings()) + .setNegativeButton(R.string.quick_reader_action_dismiss, + (dialog, i) -> finish()) + .show(); + } + + private void postAnalyze(int result) { + if (result == 0 || !sHelper.isValid()) { + return; + } + + showScanResult(result); + } + + private void showScanResult(int imageResource) { + mIdentifyIcon.setImageResource(imageResource); + + if (mIdentifyLayout.getScaleX() == 0) { + // First shown, animate + mIdentifyLayout.animate() + .scaleX(1) + .scaleY(1) + .start(); + } + } + + private void toggleFlash() { + boolean isEnabled = mScanView.getFlash(); + mScanView.setFlash(!isEnabled); + mFlashIcon.setImageResource(isEnabled ? R.drawable.ic_flash_off : R.drawable.ic_flash_on); + } + + private static class AnalyzeTask extends AsyncTask<String, Void, Integer> { + private static final String ID_SMS = "smsto:"; + private static final String ID_EMAIL = "mailto:"; + private static final String ID_PHONE = "tel:"; + private static final String ID_LOCATION = "geo:"; + private static final String ID_VCARD = "BEGIN:VCARD"; + private static final String ID_VEVENT = "BEGIN:VEVENT"; + private static final String ID_MECARD = "MECARD:"; + private static final String ID_MEBKM_URL = "MEBKM:TITLE:"; + + @Override + protected Integer doInBackground(String... params) { + if (params.length == 0) { + return null; + } + + String content = params[0]; + int icon; + + if (TextUtils.isEmpty(content)) { + return null; + } + + sHelper.reset(); + + if (content.startsWith(ID_SMS)) { + icon = R.drawable.ic_sms; + sHelper.setSMSIntent(content); + } else if (content.startsWith(ID_EMAIL)) { + icon = R.drawable.ic_email; + } else if (content.startsWith(ID_PHONE)) { + icon = R.drawable.ic_phone; + sHelper.setUriIntent(content); + } else if (content.startsWith(ID_LOCATION)) { + sHelper.setUriIntent(content); + icon = R.drawable.ic_location; + } else if (content.startsWith(ID_VEVENT)) { + sHelper.setCalendarIntent(content); + icon = R.drawable.ic_event; + } else if (content.startsWith(ID_MECARD)) { + sHelper.setContactIntent(content.replace(ID_MECARD, ""), false); + icon = R.drawable.ic_contact; + } else if (content.startsWith(ID_VCARD)) { + sHelper.setContactIntent(content, true); + icon = R.drawable.ic_contact; + } else if (content.startsWith(ID_MEBKM_URL)) { + sHelper.setMeBkmUrl(content); + icon = R.drawable.ic_http; + } else { + String properContent = smartUrlFilter(content); + + if (TextUtils.isEmpty(properContent)) { + // Fallback to plain text + sHelper.setText(content); + return R.drawable.ic_text; + } + + sHelper.setUriIntent(properContent); + icon = R.drawable.ic_http; + } + + return icon; + } + + /** + * Attempts to determine whether user input is a URL or search + * terms. Anything with a space is passed to search if canBeSearch is true. + * + * Converts to lowercase any mistakenly uppercased schema (i.e., + * "Http://" converts to "http://" + * + * @return Original or modified URL + * + */ + private String smartUrlFilter(String url) { + String inUrl = url.trim(); + boolean hasSpace = inUrl.indexOf(' ') != -1; + + Matcher matcher = ACCEPTED_URI_SCHEMA.matcher(inUrl); + if (matcher.matches()) { + // force scheme to lowercase + String scheme = matcher.group(1); + String lcScheme = scheme.toLowerCase(); + if (!lcScheme.equals(scheme)) { + inUrl = lcScheme + matcher.group(2); + } + if (hasSpace && Patterns.WEB_URL.matcher(inUrl).matches()) { + inUrl = inUrl.replace(" ", "%20"); + } + return inUrl; + } + if (!hasSpace && Patterns.WEB_URL.matcher(inUrl).matches()) { + return URLUtil.guessUrl(inUrl); + } + return null; + } + } +}
\ No newline at end of file |