问题
I have an app where I want to build 2 different flow's in:
- 1.a App is open on any activity
1.b App show's an alertbox where user can choose to go to the activity regarding the notification or stay on the current activity.
2.a App is running in background
- 2.b Notification in notification bar, starts the activity regarding to the notification.
I currently have flow 2 working, but cannot find out how to get flow 1 working. Here's some code:
In GcmIntentService:
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that GCM will be
* extended in the future with new message types, just ignore any message types you're
* not interested in, or that you don't recognize.
*/
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
Log.e("GCM", "Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
Log.e("GCM", "Deleted messages on server: " + extras.toString());
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
// Post notification of received message.
sendNotification(extras);
Log.i(TAG, "Received: " + extras.toString());
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
// Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(Bundle extras) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
String message = extras.getString("message");
Intent openIntent = new Intent(this, HomeActivity.class);
if (extras != null) {
if (extras.containsKey("tipid")) {
openIntent.putExtra("tipid", extras.getString("tipid"));
} else if (extras.containsKey("discussionid")) {
openIntent.putExtra("discussionid", extras.getString("discussionid"));
}
}
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
openIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("StadseBoeren")
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message))
.setContentText(message);
mBuilder.setContentIntent(contentIntent)
.setAutoCancel(true);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
GcmBroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
The HomeActivity onCreate:
Bundle extras = intent.getExtras();
if (extras != null) {
if (extras.containsKey("tipid")) {
pendingObjectId = extras.getString("tipid");
modelFlag = ModelFlag.TIP;
} else if (extras.containsKey("discussionid")) {
pendingObjectId = extras.getString("discussionid");
modelFlag = ModelFlag.DISCUSSION;
}
}
回答1:
Make a class extends Application and implement ActivityLifecycleCallbacks and according to on pause and onResume update a public boolean.
At the time push received check this Boolean and perform as your requirement.
Hope this will help you
public class TestApplication extends Application implements ActivityLifecycleCallbacks{
boolean applicationOnPause = false;
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityCreated(Activity arg0, Bundle arg1) {
Log.e("","onActivityCreated");
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.e("","onActivityDestroyed ");
}
@Override
public void onActivityPaused(Activity activity) {
applicationOnPause = true;
Log.e("","onActivityPaused "+activity.getClass());
}
@Override
public void onActivityResumed(Activity activity) {
applicationOnPause = false;
Log.e("","onActivityResumed "+activity.getClass());
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.e("","onActivitySaveInstanceState");
}
@Override
public void onActivityStarted(Activity activity) {
Log.e("","onActivityStarted");
}
@Override
public void onActivityStopped(Activity activity) {
Log.e("","onActivityStopped");
}
}
回答2:
I'd just write another BroadcastReceiver
like this:
public class MainActivityBroadcastReceiver extends BroadcastReceiver {
public MainActivityBroadcastReceiver(Activity mainActivity) {
}
@Override
public void onReceive(Context context, Intent intent) {
Toast toast = Toast.makeText(context, "hola", Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
}
}
and then in the MainActivity
I'd override the methods and then I don't receive the notification so I intercept the `Intent~ and abort the other broadcast:
@Override
protected void onPause() {
unregisterReceiver(mainActivityBroadcastReceiver);
super.onPause();
}
@Override
public void onResume() {
IntentFilter filter = new IntentFilter("com.google.android.c2dm.intent.RECEIVE");
filter.setPriority(1);
registerReceiver(mainActivityBroadcastReceiver, filter);
super.onResume();
}
回答3:
In my code I have public static ArrayList<Activity> activity_stack
every activity is added in oncreate and removed in ondestroy methods. I check this stack in GcmBroadcastReceiver. I don't know if it's a good solution.
回答4:
A solution I just found does require a GET_TASK permission:
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = activityManager
.getRunningTasks(Integer.MAX_VALUE);
boolean isActivityFound = false;
if (services.get(0).topActivity.getPackageName().toString()
.equalsIgnoreCase(getApplicationContext().getPackageName().toString())) {
isActivityFound = true;
}
Log.d("GCM", "Activity open: "+isActivityFound);
UPDATE
In order to launch an alertbox (which isn't possible here) I created a custom alert box and let it use the AlertBox as theme. This is the activity in AndroidManifest.xml:
<activity
android:name="nl.raakict.android.stadseboeren.NotificationAlertActivity"
android:label="@string/title_activity_notification_alert"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Dialog" >
And the custom activity:
public class NotificationAlertActivity extends Activity implements
Observer, OnClickListener {
private String pendingObjectId;
private ModelFlag modelFlag;
private Database db;
private ArrayList<Discussion> discussions;
private ArrayList<Tip> tips;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_alert);
findViewById(R.id.button_yes).setOnClickListener(this);
findViewById(R.id.button_no).setOnClickListener(this);
}
I updated the onHandleIntent with this bit:
if (isActivityFound) {
Intent dialogIntent = new Intent(getBaseContext(),
NotificationAlertActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
}
来源:https://stackoverflow.com/questions/23558986/gcm-how-do-i-detect-if-app-is-open-and-if-so-pop-up-an-alert-box-instead-of-nor