173

Android:

public class LocationService extends Service {

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        startActivity(new Intent(this, activity.class));
    }
}

I launched this service from Activity

In Activity if condition satisfies start

startService(new Intent(WozzonActivity.this, LocationService.class));

from my LocationService mentioned above could not launch Activity, how can I get context of current running Activity in service class?

Ryan M
  • 18,333
  • 31
  • 67
  • 74
d-man
  • 57,473
  • 85
  • 212
  • 296

11 Answers11

378

From inside the Service class:

Intent dialogIntent = new Intent(this, MyActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dialogIntent);

But, this does not work from Android 10+ due to battery optimisation restrictions

Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
d-man
  • 57,473
  • 85
  • 212
  • 296
26

UPDATE ANDROID 10 AND HIGHER

Start an activity from service (foreground or background) is no longer allowed.

There are still some restrictions that can be seen in the documentation

https://developer.android.com/guide/components/activities/background-starts

José Braz
  • 575
  • 5
  • 9
  • 2
    @RahulBhobe I found this answer helpful, because adding the `SYSTEM_ALERT_WINDOW` (and enabling it in the settings) solved my issue on Android 10. – Daniel F Sep 05 '20 at 07:32
  • 1
    SYSTEM_ALERT_WINDOW can not be granted in Go Edition devices. – Shrdi Mar 29 '21 at 11:25
  • @Shrdi, so, do you have any solutions for AndroidGo? – AlexS Aug 12 '21 at 16:45
  • @AlexS I don't think this can work on Android 10+Go because this is the system limitation. Any feature about this should offer another alternative way or hint, user might not agree this permission as well. – Shrdi Aug 14 '21 at 04:30
20

I had the same problem, and want to let you know that none of the above worked for me. What worked for me was:

 Intent dialogIntent = new Intent(this, myActivity.class);
 dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 this.startActivity(dialogIntent);

and in one my subclasses, stored in a separate file I had to:

public static Service myService;

myService = this;

new SubService(myService);

Intent dialogIntent = new Intent(myService, myActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myService.startActivity(dialogIntent);

All the other answers gave me a nullpointerexception.

Nikhil Agrawal
  • 26,128
  • 21
  • 90
  • 126
Andy
  • 2,469
  • 1
  • 25
  • 25
10

Another thing worth mentioning: while the answer above works just fine when our task is in the background, the only way I could make it work if our task (made of service + some activities) was in the foreground (i.e. one of our activities visible to user) was like this:

    Intent intent = new Intent(storedActivity, MyActivity.class);
    intent.setAction(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    storedActivity.startActivity(intent);

I do not know whether ACTION_VIEW or FLAG_ACTIVITY_NEW_TASK are of any actual use here. The key to succeeding was

storedActivity.startActivity(intent);

and of course FLAG_ACTIVITY_REORDER_TO_FRONT for not instantiating the activity again. Best of luck!

kellogs
  • 2,837
  • 3
  • 38
  • 51
  • 1
    This does not work. All this gives me is the error "Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?" – Cerin Jul 18 '12 at 00:49
  • 5
    This is because the second call to setFlags overrides the first one. This solution should use addFlags, or a single call to set flags that passes Intent.FLAG_ACTIVITY_NEW_TASK && Intent.FLAG_ACTIVITY_REORDER_TO_FRONT. – Fergusmac Jul 12 '13 at 00:23
  • 8
    You don't want to combine flags with &&; you want to use | (a single bar for bitwise or) – Jon Watte Sep 20 '13 at 21:02
  • Intent intent = new Intent(storedActivity, MyActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); storedActivity.startActivity(intent); – Prakhar Kulshreshtha Oct 03 '17 at 10:49
2

The new way from android 10 and greater is SYSTEM_ALERT_WINDOW permission. Here is how you do it: Within AndroidManifiest.xml file declare this permission

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

Within onCreate method on button click, call a helper method to show a dialog that way if a user opted in to allow permission, device settings for overlay permission will open. Note that this on Click button is just for you to get an idea on how to invoke permission. You can invoke it which ever way you like per your app requirements.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);      
    Button button = (Button) findViewById(R.id.button1);

    button.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            showMessageForFloatingPermission("To use this feature requires over lay permission");
        }
    });
}

Below are helper methods declared?

//Helper method to show a dialog window
private void showMessageForFloatingPermission(String message) {
    new android.app.AlertDialog.Builder(MainActivity.this)
            .setMessage(message)
            .setPositiveButton("OK",  new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    checkFloatingPermission();

                }
            })
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    //User opted not to use this feature
                    //finish();

                }
            })
            .create()
            .show();
}





//Helper method for checking over lay floating permission
public void checkFloatingPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityFloatingPermission.launch(intent);//this will open device settings for over lay permission window

        }
    }
}





//Initialize ActivityResultLauncher. Note here that no need custom request code
ActivityResultLauncher<Intent> startActivityFloatingPermission = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    //Permission granted
                }else{
                    //If there is no permission allowed yet, still a dialog window will open unless a user opted not to use the feature. 
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        if (!Settings.canDrawOverlays(MainActivity.this)) {
                            // You don't have permission yet, show a dialog reasoning
                            showMessageForFloatingPermission("To use this feature requires over lay permission");

                        }
                    }
                }
            }
        });

Once you implemented above codes accordingly, you can start any activity from service class. Your activity will be launched programmatically.

Intent intent = new Intent(this, MyActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);

Basically, this is how you can do it. It works good. BTW, you can manipulate this code as you like per your desires. Hopefully, this will help!!

Yosidroid
  • 2,053
  • 16
  • 15
1

one cannot use the Context of the Service; was able to get the (package) Context alike:

Intent intent = new Intent(getApplicationContext(), SomeActivity.class);
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
1

You can also use getApplicationContext() method in your Service to run the startActivity() method as written below:

Intent myIntent = new Intent();
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(myIntent);
Gaur 97
  • 73
  • 5
0

If you need to recal an Activity that is in bacgrounde, from your service, I suggest the following link. Intent.FLAG_ACTIVITY_NEW_TASK is not the solution.

https://stackoverflow.com/a/8759867/1127429

Community
  • 1
  • 1
GMG
  • 1,498
  • 14
  • 20
0

Alternately,

You can use your own Application class and call from wherever you needs (especially non-activities).

public class App extends Application {

    protected static Context context = null;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }

    public static Context getContext() {
        return context;
    }

}

And register your Application class :

<application android:name="yourpackage.App" ...

Then call :

App.getContext();
james
  • 1,967
  • 3
  • 21
  • 27
0

SYSTEM_ALERT_WINDOW.requrid permission in manifest and enable from from mobile seting manully its works from android 10+.

t4truth
  • 1
  • 3
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 08 '22 at 06:44
0

Xiaomi Redmi 4A, Android 7, MIUI 10.2.3. Main activity for app in debug version could not start to foreground from service. There was MIUILOG- Permission Denied Activity error in logcat. Rebuilding this app in release version fixed the problem.

Anton Samokat
  • 542
  • 1
  • 6
  • 15