Merge branch 'afWarningQrCodeScan' into 'master'
* jif-afWarningQrCodeScan: do not include english string in translations Correct check style errors Add style for the poor QR code scanning autofocus capability warning Add 'poor QR code scanning capability' translations Call to the camera autofocus checker in the view Add camera characteristics checker fdroid/fdroidclient!649 closes #260
This commit is contained in:
commit
6ad3604a0e
@ -29,6 +29,7 @@ import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.localrepo.SwapService;
|
||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||
import org.fdroid.fdroid.views.swap.device.camera.CameraCharacteristicsChecker;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
@ -63,6 +64,7 @@ public class WifiQrView extends ScrollView implements SwapWorkflowActivity.Inner
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
setUIFromWifi();
|
||||
setUpWarningMessageQrScan();
|
||||
|
||||
ImageView qrImage = (ImageView) findViewById(R.id.wifi_qr_code);
|
||||
|
||||
@ -81,6 +83,14 @@ public class WifiQrView extends ScrollView implements SwapWorkflowActivity.Inner
|
||||
onWifiStateChanged, new IntentFilter(WifiStateChangeService.BROADCAST));
|
||||
}
|
||||
|
||||
private void setUpWarningMessageQrScan() {
|
||||
final View qrWarnningMessage = findViewById(R.id.warning_qr_scanner);
|
||||
final boolean hasAutofocus = CameraCharacteristicsChecker.getInstance(getContext()).hasAutofocus();
|
||||
final int visiblity = hasAutofocus ? GONE : VISIBLE;
|
||||
qrWarnningMessage.setVisibility(visiblity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove relevant listeners/receivers/etc so that they do not receive and process events
|
||||
* when this view is not in use.
|
||||
|
@ -0,0 +1,21 @@
|
||||
package org.fdroid.fdroid.views.swap.device.camera;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public abstract class CameraCharacteristicsChecker {
|
||||
public static CameraCharacteristicsChecker getInstance(final Context context) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
return new CameraCharacteristicsMinApiLevel21(context);
|
||||
} else {
|
||||
return new CameraCharacteristicsMaxApiLevel20();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean hasAutofocus();
|
||||
|
||||
class FDroidDeviceException extends Exception {
|
||||
FDroidDeviceException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package org.fdroid.fdroid.views.swap.device.camera;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CameraCharacteristicsMaxApiLevel20 extends CameraCharacteristicsChecker {
|
||||
|
||||
private static final String TAG = "CameraCharMaxApiLevel20";
|
||||
|
||||
protected CameraCharacteristicsMaxApiLevel20() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAutofocus() {
|
||||
boolean hasAutofocus = false;
|
||||
try {
|
||||
hasAutofocus = hasDeviceAutofocusCapability();
|
||||
} catch (FDroidDeviceException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
return hasAutofocus;
|
||||
}
|
||||
|
||||
private boolean hasDeviceAutofocusCapability() throws FDroidDeviceException {
|
||||
try {
|
||||
final int numberOfCameras = Camera.getNumberOfCameras();
|
||||
if (numberOfCameras == 0) {
|
||||
Log.i(TAG, "No camera on device");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasAutofocus = false;
|
||||
for (int cameraId = 0; cameraId < numberOfCameras; cameraId++) {
|
||||
Camera camera = Camera.open(cameraId);
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
List<String> availableAFModes = parameters.getSupportedFocusModes();
|
||||
hasAutofocus = availableAFModes.contains(Camera.Parameters.FOCUS_MODE_AUTO);
|
||||
}
|
||||
|
||||
return hasAutofocus;
|
||||
} catch (Exception e) {
|
||||
String msg = "Exception accessing device camera";
|
||||
Log.e(TAG, msg, e);
|
||||
throw new FDroidDeviceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package org.fdroid.fdroid.views.swap.device.camera;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public class CameraCharacteristicsMinApiLevel21 extends CameraCharacteristicsChecker {
|
||||
|
||||
private static final String TAG = "CameraCharMinApiLevel21";
|
||||
private final CameraManager cameraManager;
|
||||
|
||||
protected CameraCharacteristicsMinApiLevel21(final Context context) {
|
||||
this.cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAutofocus() {
|
||||
boolean hasAutofocus = false;
|
||||
try {
|
||||
hasAutofocus = hasDeviceAutofocus();
|
||||
} catch (FDroidDeviceException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
return hasAutofocus;
|
||||
}
|
||||
|
||||
private boolean hasDeviceAutofocus() throws FDroidDeviceException {
|
||||
try {
|
||||
boolean deviceHasAutofocus = false;
|
||||
final String[] cameraIdList = getCameraIdList();
|
||||
|
||||
for (final String cameraId : cameraIdList) {
|
||||
if (isLensFacingBack(cameraId)) {
|
||||
deviceHasAutofocus = testAutofocusModeForCamera(cameraId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return deviceHasAutofocus;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
throw new FDroidDeviceException("Exception accessing the camera list", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String[] getCameraIdList() throws FDroidDeviceException {
|
||||
try {
|
||||
return cameraManager.getCameraIdList();
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
throw new FDroidDeviceException("Exception accessing the camera list", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLensFacingBack(final String cameraId) throws FDroidDeviceException {
|
||||
final Integer lensFacing = getCameraCharacteristics(cameraId).get(CameraCharacteristics.LENS_FACING);
|
||||
|
||||
return lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private CameraCharacteristics getCameraCharacteristics(final String cameraId) throws FDroidDeviceException {
|
||||
try {
|
||||
return cameraManager.getCameraCharacteristics(cameraId);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
throw new FDroidDeviceException("Exception accessing the camera id = " + cameraId, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean testAutofocusModeForCamera(final String cameraId) throws FDroidDeviceException {
|
||||
try {
|
||||
boolean hasAutofocusMode = false;
|
||||
final int[] autoFocusModes = getAvailableAFModes(cameraId);
|
||||
if (autoFocusModes != null) {
|
||||
hasAutofocusMode = testAvailableMode(autoFocusModes);
|
||||
}
|
||||
|
||||
return hasAutofocusMode;
|
||||
} catch (FDroidDeviceException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
throw new FDroidDeviceException("Exception accessing the camera id = " + cameraId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getAvailableAFModes(final String cameraId) throws FDroidDeviceException {
|
||||
return getCameraCharacteristics(cameraId).get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
|
||||
}
|
||||
|
||||
private boolean testAvailableMode(final int[] autoFocusModes) {
|
||||
boolean hasAutofocusMode = false;
|
||||
for (final int mode : autoFocusModes) {
|
||||
boolean afMode = isAutofocus(mode);
|
||||
hasAutofocusMode |= afMode;
|
||||
}
|
||||
return hasAutofocusMode;
|
||||
}
|
||||
|
||||
private boolean isAutofocus(final int mode) {
|
||||
return mode != android.hardware.camera2.CameraMetadata.CONTROL_AF_MODE_OFF;
|
||||
}
|
||||
|
||||
}
|
@ -44,6 +44,14 @@
|
||||
android:layout_gravity="center"
|
||||
android:id="@+id/btn_qr_scanner"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/warning_qr_scanner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/warning_scaning_qr_code"
|
||||
android:visibility="gone"
|
||||
style="@style/SwapTheme.Wizard.QRScanWarningText"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</org.fdroid.fdroid.views.swap.WifiQrView>
|
@ -563,6 +563,7 @@ This often occurs with apps installed via Google Play or other sources, if they
|
||||
</plurals>
|
||||
|
||||
<string name="details_last_updated_today">Updated today</string>
|
||||
<string name="warning_scaning_qr_code">Your camera doesn\'t seem to have an autofocus. It might be difficult to scan the code.</string>
|
||||
<plurals name="details_last_update_days">
|
||||
<item quantity="one">Updated %1$d day ago</item>
|
||||
<item quantity="other">Updated %1$d days ago</item>
|
||||
|
@ -228,12 +228,19 @@
|
||||
<style name="SwapTheme.Wizard.MainTextBase" parent="@style/SwapTheme.Wizard.Text">
|
||||
<item name="android:paddingLeft">40dp</item>
|
||||
<item name="android:paddingRight">40dp</item>
|
||||
<item name="android:paddingTop">20dp</item>
|
||||
<item name="android:paddingBottom">15dp</item>
|
||||
<item name="android:paddingTop">10dp</item>
|
||||
<item name="android:paddingBottom">10dp</item>
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.Wizard.MainText" parent="SwapTheme.Wizard.MainTextBase" />
|
||||
|
||||
<style name="SwapTheme.Wizard.QRScanWarningText" parent="@style/SwapTheme.Wizard.MainTextBase" >
|
||||
<item name="android:paddingLeft">40dp</item>
|
||||
<item name="android:paddingRight">40dp</item>
|
||||
<item name="android:paddingTop">0dp</item>
|
||||
<item name="android:paddingBottom">5dp</item>
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.Wizard.LocalIpAddress" parent="@style/SwapTheme.Wizard.Text">
|
||||
<item name="android:textSize">20sp</item>
|
||||
<item name="android:paddingLeft">40dp</item>
|
||||
|
Loading…
x
Reference in New Issue
Block a user