从 Android 中的 Service 启动 Activity

发布于 2024-09-16 19:10:51 字数 555 浏览 6 评论 0原文

Android:

public class LocationService extends Service {

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

我从 Activity 启动此服务

Activity 中,如果条件满足

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

从上面提到的 LocationService 启动,则无法启动 Activity >,如何获取服务类中当前正在运行的Activity的上下文?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

反差帅 2024-09-23 19:10:51

从 Service 类内部:

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

但是,由于电池优化限制,这在 Android 10+ 中不起作用

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

蓝天 2024-09-23 19:10:51

更新 ANDROID 10 及更高版本

不再允许从服务(前台或后台)启动活动。

仍然有一些限制可以在文档中看到

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

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

匿名。 2024-09-23 19:10:51

我遇到了同样的问题,并且想让您知道上述方法都不适合我。
对我有用的是:

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

在我的一个子类中,存储在一个单独的文件中,我必须:

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);

所有其他答案都给了我一个空指针异常。

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.

别想她 2024-09-23 19:10:51

另一件值得一提的事情是:虽然当我们的任务在后台时上面的答案工作得很好,但如果我们的任务(由服务+一些活动组成)在前台(即我们的活动之一可见),我可以让它工作的唯一方法对用户来说)是这样的:

    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);

我不知道 ACTION_VIEW 或 FLAG_ACTIVITY_NEW_TASK 在这里是否有任何实际用途。成功的关键

storedActivity.startActivity(intent);

当然是 FLAG_ACTIVITY_REORDER_TO_FRONT ,以便不再实例化活动。祝你好运!

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!

你的呼吸 2024-09-23 19:10:51

Android 10 及更高版本的新方法是 SYSTEM_ALERT_WINDOW 权限。操作方法如下:
在 AndroidManizest.xml 文件中声明此权限

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

在单击按钮时的 onCreate 方法中,调用辅助方法来显示一个对话框,这样如果用户选择允许权限,将打开覆盖权限的设备设置。请注意,单击按钮上的这个只是为了让您了解如何调用权限。您可以根据应用程序要求以您喜欢的方式调用它。

@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");
        }
    });
}

下面声明了辅助方法吗?

//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");

                        }
                    }
                }
            }
        });

一旦您相应地实现了上述代码,您就可以从服务类启动任何活动。您的活动将以编程方式启动。

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

基本上,您可以这样做。效果很好。顺便说一句,您可以按照自己的意愿操作此代码。希望这会有所帮助!

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!!

偏爱你一生 2024-09-23 19:10:51

无法使用ServiceContext;能够获得类似的(包)Context

Intent intent = new Intent(getApplicationContext(), SomeActivity.class);

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

Intent intent = new Intent(getApplicationContext(), SomeActivity.class);
沉溺在你眼里的海 2024-09-23 19:10:51

您还可以在Service中使用getApplicationContext()方法来运行startActivity() 方法如下:

Intent myIntent = new Intent();
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(myIntent);

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);
深海夜未眠 2024-09-23 19:10:51

在 Service 类中,我们可以使用 this 关键字来引用上下文。

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        val mIntent = Intent(this, YourActivity::class.java).apply {
            setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) // set flags if you needed
            putExtra("yourKey", "yourValue")
        }

        startActivity(mIntent)

    }

Inside the Service class, we can use the this keyword to refer to the context.

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        val mIntent = Intent(this, YourActivity::class.java).apply {
            setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) // set flags if you needed
            putExtra("yourKey", "yourValue")
        }

        startActivity(mIntent)

    }
两人的回忆 2024-09-23 19:10:51

如果您需要从您的服务中重新调用 bacgrounde 中的活动,我建议您使用以下链接。 Intent.FLAG_ACTIVITY_NEW_TASK 不是解决方案。

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

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

自此以后,行同陌路 2024-09-23 19:10:51

或者,

您可以使用自己的应用程序类并从您需要的任何地方(尤其是非活动)进行调用。

public class App extends Application {

    protected static Context context = null;

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

    public static Context getContext() {
        return context;
    }

}

并注册您的应用程序类:

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

然后调用:

App.getContext();

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();

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

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

和影子一齐双人舞 2024-09-23 19:10:51

小米红米4A,安卓7,MIUI 10.2.3。 debug 版本中应用的主要活动无法从服务启动到前台。 logcat 中存在 MIUILOG- Permission Denied Activity 错误。在 release 版本中重建此应用程序修复了该问题。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文