Reputation: 343
The scenario: When the app is asleep or in the background, a notification is sent to the device. User clicks the notification and expects the application to be open given the current activity displayed on the background.
The solutions I've tried so far.. In my
NotificationLister extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
//I directy
Intent intent = new Intent(this, MyActivity.class);
//pass necessary extras here and flags
getApplication().startActivity(intent);
}
}
^ the above works fine given that I know already what activity is currently present when the app is brought to foreground BUT when I do not exactly know what activity is present.. (let's say we have two activities that are mainly used which are -- MyActivity
and MyOtherActivity
), this now won't work since on onResume() of MyOtherActivity
, getIntent().getExtras()
won't contain the new extras being set at my NotificationListener service class since MyActivity.class
is explicitly defined.
And so I tried the solution #4 from this answer Android: How can I get the current foreground activity (from a service)? so that I can dynamically pass extras and reopen the said current activity. And this now brings me to the problem below.
The problem:
Intent.ACTION_USER_FOREGROUND
is somewhat restricted with this error Permission Denial: not allowed to send broadcast android.intent.action.USER_FOREGROUND
I'm seeing similar solutions which is to declare this in the manifest file <uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions"/>
but it doesn't really solve my problem, the same issue is being logged.
What proper Intent.action
can we use in this scenario? or is there another proper way to handle this?
Manifest.xml
<service android:name=".NotificationListener"/>
<receiver android:name=".MyBroadcastReceiver"/>
MyOtherActivity.java
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_FOREGROUND);
BroadcastReceiver mReceiver = new MyBroadcastReceiver();
registerReceiver(mReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
//I think it could also be okay to registerReceiver here
}
@Override
public void onDestroy() {
this.unregisterReceiver(broadcastReceiver);
super.onDestroy();
//on debug this is always called after sendBroadcast() and then the Permission Denial error
}
NotificationListener.class
NotificationLister extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
Intent broadcastIntent = new Intent();
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.setAction(Intent.ACTION_USER_FOREGROUND);
broadcastIntent.putExtra("myNecessaryExtra", intent.getStringExtra("test"));
sendBroadcast(broadcastIntent);
}
}
MyBroadcastReceiver.class
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String responseString = intent.getStringExtra("myNecessaryExtra");
//on debug this doesn't get called because of the Permission Denial error
}
}
Upvotes: 0
Views: 275
Reputation: 343
For people who'd also have the same concern.. and would like to try out some solutions
This is what I used to fix mine
- Use your activities showingInstance.. so when the application is brought to background I made sure my activities showingInstance doesn't get cleared.
- Made use of the onTrimMemory() method
- So when a message has been received, I check if what showingInstance is available and pass the necessary extras to that specific activity.
//MyActivity.java
@Override
protected void onPause() {
//when the activity is brought to the background
//do not clear its activityInstance
}
public boolean isInBackground() {
return ((MyApplication) getApplication()).appIsInBackground();
}
//MessagingService.java
@Override
public void onMessageReceived(RemoteMessage message) {
boolean onBackground = MyActivity.showingInstance != null && MyActivity.isInBackground();
//do the necessary processing here on showing your notification
if (onBackground) {
//bring the application to the foreground
}
}
//MyApplication.java
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN || level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
//The application here goes to the background
appIsInBackground = true;
}
}
}
Upvotes: 0