Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fallback to zxing-based lib to scan QrCodes #861

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mastodon/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ dependencies {
implementation 'com.squareup:otto:1.3.8'
implementation 'de.psdev:async-otto:1.0.3'
implementation 'com.google.zxing:core:3.5.3'
implementation 'com.github.markusfisch:BarcodeScannerView:1.6.0'
implementation 'org.microg:safe-parcel:1.5.0'
implementation 'org.parceler:parceler-api:1.1.12'
annotationProcessor 'org.parceler:parceler:1.1.12'
Expand Down
4 changes: 4 additions & 0 deletions mastodon/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

<permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature"/>

Expand Down Expand Up @@ -79,6 +82,7 @@
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
<activity android:name=".QrCodeScanActivity"/>

<service android:name=".AudioPlayerService" android:foregroundServiceType="mediaPlayback"/>
<service android:name=".NotificationActionHandlerService" android:exported="false"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package org.joinmastodon.android;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import android.view.HapticFeedbackConstants;
import android.view.View;

import androidx.annotation.NonNull;

import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;

import de.markusfisch.android.barcodescannerview.widget.BarcodeScannerView;

public class QrCodeScanActivity extends Activity{
private static final int PERMISSION_RESULT=65537;
private BarcodeScannerView scannerView;

@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
UiUtils.setUserPreferredTheme(this);
setContentView(R.layout.activity_qr_scan);

if(this.checkSelfPermission(Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.CAMERA}, PERMISSION_RESULT);
}

findViewById(R.id.dismiss).setOnClickListener(view -> finish());
scannerView=findViewById(R.id.scanner);
scannerView.setCropRatio(.75f);
scannerView.setOnBarcodeListener(barcode -> {
vibrate(scannerView);
Intent result=new Intent();
result.putExtra("barcode", barcode.getText());
setResult(RESULT_OK, result);
finish();
return false;
});
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
if(requestCode==PERMISSION_RESULT){
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
scannerView.openAsync();
}else if(!this.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)){
new M3AlertDialogBuilder(this)
.setTitle(R.string.permission_required)
.setMessage(R.string.camera_permission_to_scan)
.setPositiveButton(R.string.open_settings, (dialog, which)->this.startActivity(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", this.getPackageName(), null))))
.setNegativeButton(R.string.cancel, (dialogInterface, i) -> finish())
.setOnCancelListener(dialogInterface -> finish())
.show();
}
}
}


private static void vibrate(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
v.performHapticFeedback(HapticFeedbackConstants.CONFIRM);
return;
}

Vibrator vibrator=v.getContext().getSystemService(Vibrator.class);

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
VibrationEffect effect=VibrationEffect.createOneShot(75L, 128);
vibrator.vibrate(effect);
} else {
vibrator.vibrate(75L);
}
}


@Override
public void onResume() {
super.onResume();
scannerView.openAsync();
}

@Override
public void onPause() {
super.onPause();
scannerView.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;

import com.google.zxing.BarcodeFormat;
Expand All @@ -64,6 +63,7 @@
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import org.joinmastodon.android.MainActivity;
import org.joinmastodon.android.QrCodeScanActivity;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.session.AccountSessionManager;
Expand Down Expand Up @@ -127,7 +127,10 @@ public void onCreate(Bundle savedInstanceState){
accountID=getArguments().getString("account");
account=Parcels.unwrap(getArguments().getParcelable("targetAccount"));
setCancelable(false);
scannerIntent=BarcodeScanner.createIntent(Barcode.FORMAT_QR_CODE, false, true);
scannerIntent=GmsClient.isGooglePlayServicesAvailable(getActivity())
? BarcodeScanner.createIntent(Barcode.FORMAT_QR_CODE, false, true)
: new Intent(getActivity(), QrCodeScanActivity.class);

}

@Override
Expand Down Expand Up @@ -265,11 +268,9 @@ public void dismiss(){

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
if(GmsClient.isGooglePlayServicesAvailable(getActivity())){
MenuItem item=menu.add(0, 0, 0, R.string.scan_qr_code);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
item.setIcon(R.drawable.ic_qr_code_scanner_24px);
}
MenuItem item=menu.add(0, 0, 0, R.string.scan_qr_code);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
item.setIcon(R.drawable.ic_qr_code_scanner_24px);
}

@Override
Expand Down Expand Up @@ -330,11 +331,15 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode==SCAN_RESULT && resultCode==Activity.RESULT_OK && BarcodeScanner.isValidResult(data)){
Barcode code=BarcodeScanner.getResult(data);
if(requestCode==SCAN_RESULT && resultCode==Activity.RESULT_OK){
String code=data.getStringExtra("barcode");
if(BarcodeScanner.isValidResult(data)){
Barcode barcode=BarcodeScanner.getResult(data);
code=barcode.rawValue;
}
if(code!=null){
if(code.rawValue.startsWith("https:") || code.rawValue.startsWith("http:")){
((MainActivity)getActivity()).handleURL(Uri.parse(code.rawValue), accountID);
if(code.startsWith("https:") || code.startsWith("http:")){
((MainActivity)getActivity()).handleURL(Uri.parse(code), accountID);
dismiss();
}else{
Toast.makeText(themeWrapper, R.string.link_not_supported, Toast.LENGTH_SHORT).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import android.widget.Toast;

import org.joinmastodon.android.MainActivity;
import org.joinmastodon.android.QrCodeScanActivity;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.ScrollableToTop;
import org.joinmastodon.android.googleservices.GmsClient;
Expand Down Expand Up @@ -70,7 +71,9 @@ public void onCreate(Bundle savedInstanceState){
setRetainInstance(true);

accountID=getArguments().getString("account");
scannerIntent=BarcodeScanner.createIntent(Barcode.FORMAT_QR_CODE, false, true);
scannerIntent=GmsClient.isGooglePlayServicesAvailable(getActivity())
? BarcodeScanner.createIntent(Barcode.FORMAT_QR_CODE, false, true)
: new Intent(getActivity(), QrCodeScanActivity.class);
}

@Nullable
Expand Down Expand Up @@ -186,11 +189,7 @@ public void onTabReselected(TabLayout.Tab tab){
searchView.setVisibility(View.VISIBLE);
}
searchScanQR=view.findViewById(R.id.search_scan_qr);
if(!GmsClient.isGooglePlayServicesAvailable(getActivity())){
searchScanQR.setVisibility(View.GONE);
}else{
searchScanQR.setOnClickListener(v->openQrScanner());
}
searchScanQR.setOnClickListener(v->openQrScanner());

View searchWrap=view.findViewById(R.id.search_wrap);
searchWrap.setOutlineProvider(OutlineProviders.roundedRect(28));
Expand Down Expand Up @@ -280,11 +279,15 @@ public void onFragmentResult(int reqCode, boolean success, Bundle result){

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode==SCAN_RESULT && resultCode==Activity.RESULT_OK && BarcodeScanner.isValidResult(data)){
Barcode code=BarcodeScanner.getResult(data);
if(requestCode==SCAN_RESULT && resultCode==Activity.RESULT_OK){
String code=data.getStringExtra("barcode");
if(BarcodeScanner.isValidResult(data)){
Barcode barcode=BarcodeScanner.getResult(data);
code=barcode.rawValue;
}
if(code!=null){
if(code.rawValue.startsWith("https:") || code.rawValue.startsWith("http:")){
((MainActivity)getActivity()).handleURL(Uri.parse(code.rawValue), accountID);
if(code.startsWith("https:") || code.startsWith("http:")){
((MainActivity)getActivity()).handleURL(Uri.parse(code), accountID);
}else{
Toast.makeText(getActivity(), R.string.link_not_supported, Toast.LENGTH_SHORT).show();
}
Expand Down
26 changes: 26 additions & 0 deletions mastodon/src/main/res/layout/activity_qr_scan.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">

<de.markusfisch.android.barcodescannerview.widget.BarcodeScannerView
android:id="@+id/scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

<ImageButton
android:id="@+id/dismiss"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|top"
android:background="?android:selectableItemBackground"
android:contentDescription="@string/back"
android:padding="16dp"
android:src="@drawable/ic_arrow_back"
android:tint="@android:color/white"
android:layout_margin="16dp"/>
</FrameLayout>
1 change: 1 addition & 0 deletions mastodon/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@
<string name="download">Download</string>
<string name="permission_required">Permission required</string>
<string name="storage_permission_to_download">The app needs access to your storage to save this file.</string>
<string name="camera_permission_to_scan">The app needs access to your camera to scan.</string>
<string name="open_settings">Open settings</string>
<string name="error_saving_file">Error saving file</string>
<string name="file_saved">File saved</string>
Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dependencyResolutionManagement {
google()
mavenCentral()
mavenLocal()
maven { url 'https://jitpack.io' }
}
}
rootProject.name = "Mastodon"
Expand Down