Skip to content
This repository has been archived by the owner on Jan 18, 2022. It is now read-only.

Commit

Permalink
v0.3.2; fix write external storage permission; add click to dismiss f…
Browse files Browse the repository at this point in the history
…or picture taken notification
  • Loading branch information
Jerry Chen committed Jul 18, 2019
1 parent d002dfe commit 31459fb
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 62 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ android {
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "0.3.1"
versionName "0.3.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resConfigs "xxhdpi"
}
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

<uses-feature
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/java/jerryc05/unlockme/activities/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ public final class MainActivity extends Activity
implements OnClickListener, OnCheckedChangeListener {

final static String
TAG = MainActivity.class.getSimpleName();
TAG = MainActivity.class.getSimpleName();
public final static int
REQUEST_CODE_DEVICE_ADMIN = 0,
REQUEST_CODE_CAMERA = 1;
REQUEST_CODE_DEVICE_ADMIN = 0,
REQUEST_CODE_CAMERA_AND_WRITE_EXTERNAL = 1;

public ReentrantLock requestDeviceAdminLock;
public static ThreadPoolExecutor threadPoolExecutor;

@IntDef({REQUEST_CODE_DEVICE_ADMIN, REQUEST_CODE_CAMERA})
@IntDef({REQUEST_CODE_DEVICE_ADMIN, REQUEST_CODE_CAMERA_AND_WRITE_EXTERNAL})
@Retention(RetentionPolicy.SOURCE)
private @interface RequestCodes {
}
Expand Down Expand Up @@ -127,7 +127,7 @@ protected void onActivityResult(@RequestCodes int requestCode,
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE_CAMERA)
if (requestCode == REQUEST_CODE_CAMERA_AND_WRITE_EXTERNAL)
CameraBaseAPIClass.onRequestPermissionFinished(
this, grantResults);
}
Expand Down
51 changes: 31 additions & 20 deletions app/src/main/java/jerryc05/unlockme/helpers/UserInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import static android.content.Context.NOTIFICATION_SERVICE;
import static jerryc05.unlockme.services.ForegroundService.ACTION_UPDATE_NOTIFICATION;
import static jerryc05.unlockme.services.ForegroundService.EXTRA_CANCEL_NOTIFICATION_ID;

/**
* A collection class for commonly used User Interface methods.
Expand Down Expand Up @@ -86,6 +87,8 @@ public static void showExceptionToNotificationNoRethrow(
@NonNull final String contentText, @Nullable final String subText,
@NonNull final Context context) {
final String title = "Crash Report";
final int id = title.hashCode();

final Builder builder = new Builder(context)
.setContentTitle(title)
.setTicker(title)
Expand All @@ -94,20 +97,21 @@ public static void showExceptionToNotificationNoRethrow(
.setSubText(subText)
.setStyle(new Notification.BigTextStyle()
.bigText(contentText))
.setContentIntent(getUpdateNotificationPendingIntent(context));
.setContentIntent(getUpdateNotificationPendingIntent(id, context));

getNotificationManager(context).notify(title.hashCode(),
setNotificationChannel(builder, getNotificationManager(context),
"Crash Report",
"Crash report notification channel for UnlockMe",
true).build());
getNotificationManager(context).notify(id, setNotificationChannel(
builder, getNotificationManager(context),
"Crash Report",
"Crash report notification channel for UnlockMe",
true).build());
}

@SuppressWarnings("unused")
public static void notifyPictureToUI(@NonNull final String contentText,
@NonNull final byte[] bytes,
@NonNull final Context context) {
final String title = "Picture Taken";
final int id = title.hashCode();

final Builder builder = new Builder(context)
.setContentTitle(title)
Expand All @@ -117,20 +121,25 @@ public static void notifyPictureToUI(@NonNull final String contentText,
.setStyle(new Notification.BigPictureStyle()
.bigPicture(BitmapFactory.decodeByteArray(
bytes, 0, bytes.length)))
.setContentIntent(getUpdateNotificationPendingIntent(context));
.setContentIntent(getUpdateNotificationPendingIntent(id, context));

getNotificationManager(context).notify(title.hashCode(),
setNotificationChannel(builder, getNotificationManager(context),
"Image Captured Report",
"Image captured report notification channel for UnlockMe",
false).build());
getNotificationManager(context).notify(id, setNotificationChannel(
builder, getNotificationManager(context),
"Image Captured Report",
"Image captured report notification channel for UnlockMe",
false).build());
}

/**
* @param cancelNotificationID pass -1 to stop dismissing notification.
*/
private static PendingIntent getUpdateNotificationPendingIntent(
final int cancelNotificationID,
@NonNull final Context context) {

final Intent intent = new Intent(context, ForegroundService.class);
intent.setAction(ACTION_UPDATE_NOTIFICATION);
intent.putExtra(EXTRA_CANCEL_NOTIFICATION_ID, cancelNotificationID);

final PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
Expand Down Expand Up @@ -163,17 +172,20 @@ public static void notifyToForegroundService(@NonNull final Service service) {
public static void notifyToUI(@NonNull final String title,
@NonNull final String contentText,
@NonNull final Context context) {
final int id = title.hashCode();

@SuppressLint("IconColors") final Builder builder = new Builder(context)
.setContentTitle(title)
.setTicker(title)
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_launcher_smartphone_lock_foreground);
.setSmallIcon(R.drawable.ic_launcher_smartphone_lock_foreground)
.setAutoCancel(true);

getNotificationManager(context).notify(title.hashCode(),
setNotificationChannel(builder, getNotificationManager(context),
"UnlockMe Notification Channel",
"Regular notification channel for UnlockMe",
true).build());
getNotificationManager(context).notify(id, setNotificationChannel(
builder, getNotificationManager(context),
"UnlockMe Notification Channel",
"Regular notification channel for UnlockMe",
true).build());
}

@SuppressWarnings("WeakerAccess")
Expand Down Expand Up @@ -210,8 +222,7 @@ static Builder setNotificationChannel(
return builder;
}

@SuppressWarnings("WeakerAccess")
static NotificationManager getNotificationManager(
public static NotificationManager getNotificationManager(
@NonNull final Context context) {
return (NotificationManager)
context.getSystemService(NOTIFICATION_SERVICE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
import jerryc05.unlockme.R;
import jerryc05.unlockme.helpers.UserInterface;

import static jerryc05.unlockme.activities.MainActivity.REQUEST_CODE_CAMERA;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static jerryc05.unlockme.activities.MainActivity.REQUEST_CODE_CAMERA_AND_WRITE_EXTERNAL;

@WorkerThread
public abstract class CameraBaseAPIClass {
Expand All @@ -43,6 +44,12 @@ public abstract class CameraBaseAPIClass {
SP_KEY_PREFER_CAMERA_API_2 = "prefer_camera_api_2",
EXTRA_CAMERA_FACING = "EXTRA_CAMERA_FACING";

private static final boolean canUseCamera2 =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
private static boolean isFront = true;
@SuppressWarnings("CanBeFinal")
static int imageCount = 5;

@SuppressWarnings("unused")
@StringDef(SP_NAME_CAMERA)
@Retention(RetentionPolicy.SOURCE)
Expand All @@ -61,12 +68,6 @@ public abstract class CameraBaseAPIClass {
public @interface IntentExtraKeys {
}

private static final boolean canUseCamera2 =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
private static boolean isFront = true;
@SuppressWarnings("CanBeFinal")
static int imageCount = 5;

@SuppressWarnings("unused")
public static void getImageFromDefaultCamera(
@NonNull final Context context,
Expand Down Expand Up @@ -116,7 +117,7 @@ public static void getImageFromCamera2(
public static boolean requestPermissions(
@NonNull final Context context) {
if (!context.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
UserInterface.showExceptionToDialog(new UnsupportedOperationException(
"requestPermissions() Camera device not found!"), context);
}
Expand All @@ -127,20 +128,25 @@ public static boolean requestPermissions(
"requestPermissions() External storage not writable!"), context);

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
context.checkSelfPermission(Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED)
(context.checkSelfPermission(Manifest.permission.CAMERA) ==
PERMISSION_GRANTED && context.checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PERMISSION_GRANTED))
return true;

if (context instanceof Activity)
if (((Activity) context).shouldShowRequestPermissionRationale(
Manifest.permission.CAMERA)) {
Manifest.permission.CAMERA) ||
((Activity) context).shouldShowRequestPermissionRationale(
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(context)
.setTitle("Permission Required")
.setMessage("We need CAMERA permissions to work properly!")
.setMessage("We need the following permissions to work properly:\n" +
"\n-\t\tCAMERA\n-\t\tWRITE_EXTERNAL_STORAGE")
.setIcon(R.drawable.ic_round_warning)
.setCancelable(false)
.setPositiveButton("OK",
Expand All @@ -151,7 +157,7 @@ public void run() {
});
} else
((Activity) context).requestPermissions(getPermissionsArray(),
REQUEST_CODE_CAMERA);
REQUEST_CODE_CAMERA_AND_WRITE_EXTERNAL);

return false;
}
Expand All @@ -165,25 +171,32 @@ static OnClickListener getRequestPermissionRationaleOnClickListener(
public void onClick(DialogInterface dialogInterface,
int i) {
activity.requestPermissions(getPermissionsArray(),
REQUEST_CODE_CAMERA);
REQUEST_CODE_CAMERA_AND_WRITE_EXTERNAL);
}
};
}

@SuppressWarnings("WeakerAccess")
static String[] getPermissionsArray() {
return new String[]{Manifest.permission.CAMERA};
return new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
}

public static void onRequestPermissionFinished(
@NonNull final Activity activity,
@NonNull final int[] grantResults) {
final boolean granted = grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean granted = true;
if (grantResults.length > 0)
for (int result : grantResults)
if (result != PackageManager.PERMISSION_GRANTED) {
granted = false;
break;
}

final String granted_str = granted
? "Camera Permissions Granted √"
: "Camera Permissions Denied ×";
? "Camera and Write External Storage Permissions Granted √"
: "Camera or Write External Storage Permissions Denied ×";
Toast.makeText(activity, granted_str, Toast.LENGTH_SHORT).show();

if (granted)
Expand Down
38 changes: 21 additions & 17 deletions app/src/main/java/jerryc05/unlockme/services/ForegroundService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
public class ForegroundService extends Service {

static final String
TAG = ForegroundService.class.getSimpleName();
TAG = ForegroundService.class.getSimpleName();
public static final String
ACTION_UPDATE_NOTIFICATION = "ACTION_UPDATE_NOTIFICATION",
ACTION_CAPTURE_IMAGE = "ACTION_CAPTURE_IMAGE";
ACTION_UPDATE_NOTIFICATION = "ACTION_UPDATE_NOTIFICATION",
ACTION_CAPTURE_IMAGE = "ACTION_CAPTURE_IMAGE",
EXTRA_CANCEL_NOTIFICATION_ID = "EXTRA_CANCEL_NOTIFICATION_ID";
private ThreadPoolExecutor threadPoolExecutor;
MyDeviceAdminReceiver myDeviceAdminReceiver;

Expand Down Expand Up @@ -62,6 +63,9 @@ public void run() {
try {
switch (Objects.requireNonNull(intent.getAction())) {
case ACTION_UPDATE_NOTIFICATION:
UserInterface.getNotificationManager(ForegroundService.this)
.cancel(intent.getIntExtra(
EXTRA_CANCEL_NOTIFICATION_ID, -1));
notifyToForegroundService(ForegroundService.this);
break;
case ACTION_CAPTURE_IMAGE:
Expand All @@ -82,6 +86,20 @@ public void run() {
return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
super.onDestroy();

if (BuildConfig.DEBUG)
Log.d(TAG, "onDestroy: ");

unregisterReceiver(myDeviceAdminReceiver);
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdown();
threadPoolExecutor = null;
}
}

private ThreadPoolExecutor getThreadPoolExecutor() {
if (threadPoolExecutor == null) {
RejectedExecutionHandler rejectedExecutionHandler
Expand All @@ -107,20 +125,6 @@ public void rejectedExecution(Runnable runnable,
return threadPoolExecutor;
}

@Override
public void onDestroy() {
super.onDestroy();

if (BuildConfig.DEBUG)
Log.d(TAG, "onDestroy: ");

unregisterReceiver(myDeviceAdminReceiver);
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdown();
threadPoolExecutor = null;
}
}

@Override
public IBinder onBind(Intent intent) {
return null;
Expand Down

0 comments on commit 31459fb

Please sign in to comment.