Is there a way to Resume an app from a BroadcastReceiver? (in the way that the Launcher Resumes or Starts an app)
I want to do this when the device is plugged in (don't worry, this isn't going in the Play store)
It seems like you must use FLAG_ACTIVITY_NEW_TASK or else you receive a RuntimeException for "Calling startActivity() from outside of an Activity context"
public class PowerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.ACTION_POWER_CONNECTED")) {
final Intent newIntent = new Intent(context, FooActivity.class);
//newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(newIntent);
}
}
}
Related
I have an alarm application.
Flow looks like this :
WakefulBroadcastReceiver(Acquires wakelock) --->> Intent service -->> startActivity
public class AlarmService extends IntentService {
protected void onHandleIntent(Intent intent) {
Intent activityIntent = new Intent(this, TriggeredActivity.class);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
Basically WakefulBroadcaseReceiver starts an intent service using startWakefulService(). Inside intent service's onHandleIntent(), only work I am doing is further starting a new activity using startActivity(). That new activity is where I am using mediaPlayer in a loop, which sounds the alarm. That activity has a dismiss button, which waits for user click to stop the media player & activity finishes.
Now the problem I am facing is that after calling startactivity() inside intent service, I can not wait for TriggeredActivity to finish(no equivalent to startActivityForResult in Service) and then complete wakeful intent. Related link
startActivity(activityIntent);
WakefulBCastReceiver.completeWakefulIntent(intent); /* can't do here */
So I am not explicitly releasing wakelock here.
My question is will the wakelock be released automatically(link-to-death), when the process that is holding it is killed.
If yes, then in my particular scenario, I need not call WakefulBCastReceiver.completeWakefulIntent().
Yes, you need to use completeWakefulIntent.
You need to put your TriggeredActivity intent into EXTRAs.
#Override
public void onReceive(Context context, Intent intent) {
Intent intentService = new Intent(context, NotificationsIntentService.class);
// Inserting data inside the Intent
intentService.putExtra(NotificationsIntentService.EXTRA_NOTIF, new Intent(context, TriggeredActivity.class));
startWakefulService(context, intentService);
}
NotificationsIntentService.class
public class NotificationsIntentService extends IntentService {
private static final String TAG = "DebugNotifIntent";
public static final String EXTRA_NOTIF = "extra_notif";
public NotificationsIntentService(){
super(NotificationsIntentService.class.getSimpleName());
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent: ");
Intent extraIntent = intent.getParcelableExtra(EXTRA_NOTIF);
extraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(extraIntent);
NotificationWakefulBroadcastReceiver.completeWakefulIntent(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
I have managed to find a solution for my problem. I am now using a Messenger for message based cross process communication between intent service & triggered activity.
I am passing a handler - alarmServiceHandler, from intent service to activity through a messenger.
Handler alarmServiceHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
if(msg.arg1 == 1) {
completedTriggeredActivity = true;
}
}
};
Inside onHandleIntent(), I am passing handler through Messenger object in intent's extra data.
Messenger alarmServiceMessenger = new Messenger(alarmServiceHandler);
Intent activityIntent = new Intent(this, TriggeredActivity.class);
activityIntent.putExtra("AlarmServiceMessenger", alarmServiceMessenger);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
while(!completedTriggeredActivity){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
WakefulBCastReceiver.completeWakefulIntent(intent);
In TriggeredActivity, I am retrieving messenger in Dismiss button's OnClickListener, just before calling finish() on the activity. And sending back a message to AlarmService with arg = 1, implying end of processing in triggered activity.
buttonDismiss.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Messenger alarmServiceMessenger = getIntent().getParcelableExtra("AlarmServiceMessenger");
Message alarmServiceMessage = Message.obtain();
alarmServiceMessage.arg1 = 1;
try {
alarmServiceMessenger.send(alarmServiceMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
finish();
}
After starting triggered activity, I am putting AlarmService in sleep mode till boolean variable completedTriggeredActivity has not been set to true in handleMessage(). Once true, it means triggered activity has finished & now I can proceed with releasing wake lock.
I would be glad to receive comments about my approach & any suggestions towards a better solution to my problem, than the one I have deviced.
I am trying to start two services on reboot of the device using only one Broadcastreceiver. But only one service is called.
Here is my receiver:
public class FirstReciever extends BroadcastReceiver{
private static final String TAG8 = "Mytag";
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Log.i(TAG8, "Restarting App after boot");
Intent myServiceInent = new Intent(context, FirstReciever.class);
context.startService(myServiceInent);
Intent myServiceInent1 = new Intent(context, DbService.class);
context.startService(myServiceInent1);
}
}
}
To start an Activity use:
startActivity(intent);
To Start a Service use:
startService(intent);
first of all look at this.
Intent myServiceInent = new Intent(context, FirstReciever.class);
context.startService(myServiceInent);
you have given the reference of your FirstReciever.class, that should be a service.
and if that doesn't work than start a single service and start another service from first one...
I am newbie to android and I am implementing background service im my app, i am starting app on BOOT_COMPLETED process & i am calling the activity to start the app and app come on foreground. But i want to keep the app in background (Minimized) and i want to do slient login in app.
i am using below code for app start on Boot_Complete.
public class bootUpLocation extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
// here we start the service
Toast.makeText(context, "broadcast receiver start for location",
Toast.LENGTH_LONG).show();
Intent myIntent = new Intent(context, LoginActivity.class);
myIntent.addCategory(Intent.CATEGORY_HOME);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
}
I am using broadcast receiver in my app to detect incomming call and it works fine. But problem is I can not send action to activity. I mean.. I want do something in activity not in receiver. I read many tutorial but they all are performing action in receiver. Any idea ?
You can declare a BroadcastReceiver as inner class of the Activity. In this case you can directly call activity's methods:
public class MyActivity extends Activity {
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activityMethod();
}
};
private final IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");
#Override
protected void onStart() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onPause();
unregisterReceiver(receiver);
}
private void activityMethod() {
}
}
You can start the Activity using an Intent and put a command code in the Intent extra fields. In your Activity you can then decide the behaviour based on the command code or resort to a default behaviour if none is present.
You can start an activity from your receiver via the normal means:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, YourActivity.class);
startActivity(i);
}
Note though that the user is going to expect that the phone application starts up since they are receiving a phone call. It is very likely a bad idea to hijack the phone call by dumping your own activity on top of the stock dialer app.
I have a broadcast receiver which will launch an Activity onReceive.
When launched, this activity will perform a long task and call finish() at the end.
I do not want to trigger another launch of Activity when the previous Activity is still performing the long task. How can I launch only a singletask activity? I have set this in the manifest.
android:launchMode="singleTask"
In my onReceive method,
public void onReceive(Context context, Intent intent) {
Intent activity = new Intent(context, Preview.class);
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activity);
}
Don't seems to work.
The Activity class actually is a MediaRecorder which will record a video clip (say 10 sec). Thus I do not want to trigger another Activity while this recording is still incomplete.
You just need to have some way for your activity to communicate to your receiver to let it know whether or not it is already running. If you have that then you can make an if statement in the receiver that will keep it from launching multiples.
One option is a static boolean in your activity that indicates whether or not you are currently running. Then you can check that boolean from the receiver, and if it is true, then don't call startActivity().
your activity would need something like this:
public YourActivity extends Activity{
public static isRunning = false;
public void onStart(){
...
isRunning = true;
}
public void onStop(){
...
isRunning = false;
}
}
now in your receiver you can make a simple if statement that will check the value of isRunning:
public void onReceive(Context context, Intent intent) {
if(YourActivity.isRunning == false){
Intent activity = new Intent(context, Preview.class);
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activity);
}
}
Please add these flags.
public void onReceive(Context context, Intent intent) {
Intent activity = new Intent(context, Preview.class);
activity.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
context.startActivity(activity);
}