From 3a7bc22f4a07b82f9078af595616ccacc804c9c1 Mon Sep 17 00:00:00 2001 From: Jerry Chen Date: Tue, 9 Jul 2019 01:42:54 -0400 Subject: [PATCH] camera works on foreground Signed-off-by: Jerry Chen --- .idea/dictionaries/Jerry.xml | 8 + .idea/inspectionProfiles/Project_Default.xml | 43 +++++ app/build.gradle | 2 +- .../unlockme/ExampleInstrumentedTest.java | 7 - app/src/main/AndroidManifest.xml | 21 ++- .../java/jerryc05/unlockme/MainActivity.java | 150 +++++++++++++++++- .../unlockme/receivers/MyDAReceiver.java | 34 ++++ app/src/main/res/layout/activity_main.xml | 9 +- app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/device_policy.xml | 5 + .../jerryc05/unlockme/ExampleUnitTest.java | 4 - 11 files changed, 260 insertions(+), 25 deletions(-) create mode 100644 .idea/dictionaries/Jerry.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 app/src/main/java/jerryc05/unlockme/receivers/MyDAReceiver.java create mode 100644 app/src/main/res/xml/device_policy.xml diff --git a/.idea/dictionaries/Jerry.xml b/.idea/dictionaries/Jerry.xml new file mode 100644 index 0000000..d8446e9 --- /dev/null +++ b/.idea/dictionaries/Jerry.xml @@ -0,0 +1,8 @@ + + + + jerryc + unlockme + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..1ebbe68 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,43 @@ + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 4cee746..60b2f50 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion "29.0.0" defaultConfig { applicationId "jerryc05.unlockme" - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" diff --git a/app/src/androidTest/java/jerryc05/unlockme/ExampleInstrumentedTest.java b/app/src/androidTest/java/jerryc05/unlockme/ExampleInstrumentedTest.java index e139493..45d334e 100644 --- a/app/src/androidTest/java/jerryc05/unlockme/ExampleInstrumentedTest.java +++ b/app/src/androidTest/java/jerryc05/unlockme/ExampleInstrumentedTest.java @@ -17,11 +17,4 @@ */ @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - - assertEquals("jerryc05.unlockme", appContext.getPackageName()); - } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 21d66ae..c72744c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,9 +4,14 @@ package="jerryc05.unlockme" tools:ignore="GoogleAppIndexingWarning"> + + + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/jerryc05/unlockme/MainActivity.java b/app/src/main/java/jerryc05/unlockme/MainActivity.java index ea2ec24..0dbd469 100644 --- a/app/src/main/java/jerryc05/unlockme/MainActivity.java +++ b/app/src/main/java/jerryc05/unlockme/MainActivity.java @@ -1,14 +1,154 @@ package jerryc05.unlockme; - +import android.Manifest; import android.app.Activity; +import android.app.AlertDialog; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; +import android.provider.MediaStore; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +import jerryc05.unlockme.receivers.MyDAReceiver; +@SuppressWarnings("NullableProblems") public class MainActivity extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); + private final static String TAG = + MainActivity.class.getName(); + private DevicePolicyManager devicePolicyManager; + private ComponentName componentName; + private final static int REQUEST_CODE_CAMERA = 0; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + new Thread(new Runnable() { + @Override + public void run() { + handleDeviceAdmin(); + findViewById(R.id.activity_main_button_takePhoto) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + takePhoto(); + } + }); + } + }).start(); + } + + @Override + protected void onResume() { + super.onResume(); + + if (isDeviceAdminDisabled()) + requireDeviceAdmin(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String[] permissions, + int[] grantResults) { + if (requestCode == REQUEST_CODE_CAMERA) { + final String granted = grantResults.length > 0 && + grantResults[0] == PackageManager.PERMISSION_GRANTED + ? "Camera Permission Granted √" + : "Camera Permission Denied ×"; + if (BuildConfig.DEBUG) + Log.d(TAG, "onRequestPermissionsResult: " + granted); + Toast.makeText(this, + granted, Toast.LENGTH_SHORT) + .show(); + takePhoto(); + } + } + + void takePhoto() { + if (BuildConfig.DEBUG) + Log.d(TAG, "takePhoto: "); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + checkSelfPermission(Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + if (shouldShowRequestPermissionRationale( + Manifest.permission.CAMERA)) + new AlertDialog.Builder(this) + .setTitle("Permission Required") + .setMessage(getResources().getString(R.string.permission_camera_explanation)) + .setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + requestPermissions( + new String[]{Manifest.permission.CAMERA}, + REQUEST_CODE_CAMERA); + } + }) + .show(); + else + requestPermissions( + new String[]{Manifest.permission.CAMERA}, + REQUEST_CODE_CAMERA); + + } else { + final int REQUEST_IMAGE_CAPTURE = 1; + + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (takePictureIntent.resolveActivity(getPackageManager()) != null) { + startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); + } } + } + + void handleDeviceAdmin() { + devicePolicyManager = (DevicePolicyManager) + getSystemService(Context.DEVICE_POLICY_SERVICE); + componentName = new ComponentName( + getApplicationContext(), MyDAReceiver.class); + + if (isDeviceAdminDisabled()) + requireDeviceAdmin(); + } + + private boolean isDeviceAdminDisabled() { + final boolean disabled = devicePolicyManager == null || + !devicePolicyManager.isAdminActive(componentName); + + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(MainActivity.this, + disabled ? "Device Admin Disabled ×" + : "Device Admin Enabled √", Toast.LENGTH_SHORT) + .show(); + } + }); + return disabled; + } + + private void requireDeviceAdmin() { + Intent intent = new Intent( + DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + componentName); + intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, + getResources().getString(R.string.device_admin_explanation)); + + runOnUiThread(new Runnable() { + @Override + public void run() { + startActivity(intent); + } + }); + } } diff --git a/app/src/main/java/jerryc05/unlockme/receivers/MyDAReceiver.java b/app/src/main/java/jerryc05/unlockme/receivers/MyDAReceiver.java new file mode 100644 index 0000000..efdb6ae --- /dev/null +++ b/app/src/main/java/jerryc05/unlockme/receivers/MyDAReceiver.java @@ -0,0 +1,34 @@ +package jerryc05.unlockme.receivers; + +import android.app.admin.DeviceAdminReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.UserHandle; +import android.util.Log; + +import jerryc05.unlockme.BuildConfig; + +@SuppressWarnings("NullableProblems") +public class MyDAReceiver extends DeviceAdminReceiver { + + private final static String TAG = MyDAReceiver.class.getName(); + private static int failedAttempt; + + @Override + public void onPasswordFailed(Context context, Intent intent, UserHandle user) { + super.onPasswordFailed(context, intent, user); + + if (BuildConfig.DEBUG) + Log.d(TAG, "onPasswordFailed: " + ++failedAttempt); + } + + @Override + public void onPasswordSucceeded(Context context, Intent intent, UserHandle user) { + super.onPasswordSucceeded(context, intent, user); + + if (failedAttempt > 0) { + + } + failedAttempt = 0; + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a058fc1..3367a10 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,13 +5,10 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - + android:text="Take Photo!" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e531b74..b0eecc8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ UnlockMe + This app needs Device Admin to work properly. + This app needs Camera permission to work properly. diff --git a/app/src/main/res/xml/device_policy.xml b/app/src/main/res/xml/device_policy.xml new file mode 100644 index 0000000..9a5736c --- /dev/null +++ b/app/src/main/res/xml/device_policy.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/test/java/jerryc05/unlockme/ExampleUnitTest.java b/app/src/test/java/jerryc05/unlockme/ExampleUnitTest.java index 626889e..cdcbdc1 100644 --- a/app/src/test/java/jerryc05/unlockme/ExampleUnitTest.java +++ b/app/src/test/java/jerryc05/unlockme/ExampleUnitTest.java @@ -10,8 +10,4 @@ * @see Testing documentation */ public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } } \ No newline at end of file