Skip to content

Commit

Permalink
Removed need for deprecated GET_TASKS permission
Browse files Browse the repository at this point in the history
Rewritten notification-click intent handling so that we don't need to
check whether app is running or not. Instead, it sends the intent such
that it can get an 'OK' response back if the app is running; if not,
it'll start the app.
  • Loading branch information
Dan Brown committed Aug 23, 2016
1 parent d72fb73 commit 65b2a9f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 79 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ dependencies {
package="com.reactnativeproject">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_TASKS" /> <!-- <- Add this line -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- <- Add this line -->
<uses-permission android:name="android.permission.VIBRATE"/> <!-- <- Add this line -->

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
package io.neson.react.notification;

import android.content.ComponentName;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Activity;
import android.content.Intent;
import android.content.Context;
import android.content.BroadcastReceiver;

import java.util.List;

import android.util.Log;

/**
Expand All @@ -20,68 +14,56 @@
* Sends broadcast to the application, launches the app if needed.
*/
public class NotificationEventReceiver extends BroadcastReceiver {
final static String INTENT_ID = "io.neson.react.notification.NotificationEvent";
final static String NOTIFICATION_ID = "id";
final static String ACTION = "action";
final static String PAYLOAD = "payload";

@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
Log.i("ReactSystemNotification",
"NotificationEventReceiver: Received: " + extras.getString(ACTION) +
", Notification ID: " + extras.getInt(NOTIFICATION_ID) +
", payload: " + extras.getString(PAYLOAD));
sendBroadcast(context, extras);
}

Log.i("ReactSystemNotification", "NotificationEventReceiver: Recived: " + extras.getString(ACTION) + ", Notification ID: " + extras.getInt(NOTIFICATION_ID) + ", payload: " + extras.getString(PAYLOAD));

// If the application is not running or is not in foreground, start it with the notification
// passed in
if (!applicationIsRunning(context)) {
String packageName = context.getApplicationContext().getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);

launchIntent.putExtra("initialSysNotificationId", extras.getInt(NOTIFICATION_ID));
launchIntent.putExtra("initialSysNotificationAction", extras.getString(ACTION));
launchIntent.putExtra("initialSysNotificationPayload", extras.getString(PAYLOAD));
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
private void sendBroadcast(final Context context, final Bundle extras) {
Intent intent = new Intent(INTENT_ID);

context.startActivity(launchIntent);
Log.i("ReactSystemNotification", "NotificationEventReceiver: Launching: " + packageName);
} else {
sendBroadcast(context, extras); // If the application is already running in foreground, send a brodcast too
}
}
intent.putExtra("id", extras.getInt(NOTIFICATION_ID));
intent.putExtra("action", extras.getString(ACTION));
intent.putExtra("payload", extras.getString(PAYLOAD));

private void sendBroadcast(Context context, Bundle extras) {
Intent intent = new Intent("NotificationEvent");
context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int result = getResultCode();

intent.putExtra("id", extras.getInt(NOTIFICATION_ID));
intent.putExtra("action", extras.getString(ACTION));
intent.putExtra("payload", extras.getString(PAYLOAD));
if (result != Activity.RESULT_OK) {
launchApplication(context, extras);
}
}
}, null, Activity.RESULT_CANCELED, null, null);

context.sendBroadcast(intent);
Log.v("ReactSystemNotification", "NotificationEventReceiver: Broadcast Sent: NotificationEvent: " + extras.getString(ACTION) + ", Notification ID: " + extras.getInt(NOTIFICATION_ID) + ", payload: " + extras.getString(PAYLOAD));
Log.v("ReactSystemNotification",
"NotificationEventReceiver: Broadcast Sent: NotificationEvent: " +
extras.getString(ACTION) +
", Notification ID: " + extras.getInt(NOTIFICATION_ID) +
", payload: " + extras.getString(PAYLOAD));
}

private boolean applicationIsRunning(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
private void launchApplication(Context context, Bundle extras) {
String packageName = context.getApplicationContext().getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<RunningAppProcessInfo> processInfos = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.processName.equals(context.getApplicationContext().getPackageName())) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String d: processInfo.pkgList) {
Log.v("ReactSystemNotification", "NotificationEventReceiver: ok: " + d);
return true;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
return true;
}
}
launchIntent.putExtra("initialSysNotificationId", extras.getInt(NOTIFICATION_ID));
launchIntent.putExtra("initialSysNotificationAction", extras.getString(ACTION));
launchIntent.putExtra("initialSysNotificationPayload", extras.getString(PAYLOAD));
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

return false;
context.startActivity(launchIntent);
Log.i("ReactSystemNotification", "NotificationEventReceiver: Launching: " + packageName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import android.content.BroadcastReceiver;
import android.app.Activity;

import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Arguments;
Expand All @@ -21,15 +21,7 @@
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.LifecycleEventListener;

import io.neson.react.notification.NotificationManager;
import io.neson.react.notification.Notification;
import io.neson.react.notification.NotificationAttributes;
import io.neson.react.notification.NotificationEventReceiver;

import java.util.ArrayList;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;

import android.util.Log;

Expand All @@ -38,7 +30,7 @@
*
* Provides JS accessible API, bridge Java and JavaScript.
*/
public class NotificationModule extends ReactContextBaseJavaModule {
public class NotificationModule extends ReactContextBaseJavaModule implements LifecycleEventListener {
final static String PREFERENCES_KEY = "ReactNativeSystemNotification";
public Context mContext = null;
public NotificationManager mNotificationManager = null;
Expand All @@ -57,7 +49,7 @@ public NotificationModule(ReactApplicationContext reactContext) {
this.mContext = reactContext;
this.mNotificationManager = (NotificationManager) new NotificationManager(reactContext);

listenNotificationEvent();
reactContext.addLifecycleEventListener(this);
}

/**
Expand Down Expand Up @@ -282,23 +274,37 @@ private NotificationAttributes getNotificationAttributesFromReadableMap(
return notificationAttributes;
}

private void listenNotificationEvent() {
IntentFilter intentFilter = new IntentFilter("NotificationEvent");
private IntentFilter intentFilter = new IntentFilter(NotificationEventReceiver.INTENT_ID);
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {

getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();

Bundle extras = intent.getExtras();
WritableMap params = Arguments.createMap();
params.putInt("notificationID", extras.getInt(NotificationEventReceiver.NOTIFICATION_ID));
params.putString("action", extras.getString(NotificationEventReceiver.ACTION));
params.putString("payload", extras.getString(NotificationEventReceiver.PAYLOAD));

WritableMap params = Arguments.createMap();
params.putInt("notificationID", extras.getInt(NotificationEventReceiver.NOTIFICATION_ID));
params.putString("action", extras.getString(NotificationEventReceiver.ACTION));
params.putString("payload", extras.getString(NotificationEventReceiver.PAYLOAD));
sendEvent("sysModuleNotificationClick", params);

sendEvent("sysModuleNotificationClick", params);
}
}, intentFilter);
this.setResultCode(Activity.RESULT_OK);
}
};

// Activity lifecycle

public void onHostResume() {
mContext.registerReceiver(intentReceiver, intentFilter);
}

public void onHostPause() {
mContext.unregisterReceiver(intentReceiver);
}

public void onHostDestroy() {
// Nothing to do; intentReceiver will already have been unregistered by this point
// in the lifecycle.
}

}

0 comments on commit 65b2a9f

Please sign in to comment.