从应用程序类向 Android 服务广播意图时遇到问题

发布于 2024-12-21 17:34:03 字数 3148 浏览 1 评论 0原文

我有一个设置,在 Android 中运行后台服务,并附加一个 BroadcastReceiver 监听特定类型的 Intent。然后广播接收器使用这些意图来调用服务中的特定方法。下面是描述服务结构的代码:

public class MyService extends Service {

     private class ServiceBroadcastReceiver extends BroadcastReceiver {


            private MyService getMyService() {
                return MyService.this;
            }

            public IntentFilter getASReceiverFilter() {
                IntentFilter filter = new IntentFilter()
                filter.addAction(Constants.ACTION_DO_SOMETHING);
                return filter;
            }

            @Override
            public void onReceive(Context context, Intent intent) {
                // TODO Auto-generated method stub
                MyService svc = getMyService();
                String intentAction = intent.getAction();
                Log.i(Constants.LOG_TAG, "Now trying to dispatch following action: " + intentAction);
                //Dispatch to the appropriate method in MyService. 
                if (intentAction.equals(AppServiceConstants.ACTION_DO_SOMETHING)) {
                    svc.doSomething();
                } 
            }
        }


    private ServiceBroadcastReceiver mRequestReceiver = new ServiceBroadcastReceiver();


    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }


    @Override
    public void onCreate() {

        Log.i(Constants.LOG_TAG, "Service Created!");
        //Register for broadcast messages indicating the add music button was pressed
        mRequestReceiver = new ServiceBroadcastReceiver();
       registerReceiver(mRequestReceiver, mRequestReceiver.getASReceiverFilter()); 
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.i(Constants.LOG_TAG, "Service Starting ... ");

        // If we get killed, after returning from here, restart
            return START_STICKY;
    }



    /***********************************************************************************
     * Service Dispatch Methods
     */
     protected void doSomething() {
         Log.i(Constants.LOG_TAG, "Doing something"); 
     }



}

我的问题是让该服务及其广播接收器从整个应用程序捕获广播意图。如果我做类似以下的事情......

getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

它只有在我从活动中调用它时才有效。但是,我希望即使在应用程序首次启动时也能够“执行某些操作”,因此在创建 MyService 并启动它之后,我已将该语句放入 onCreate() 方法中我自己的自定义应用程序子类中。由于某种原因,当应用程序启动时,广播无法在应用程序类代码中工作,但如果我将其放入活动中的某些代码中(例如,在活动的 onCreate() 方法中),它将起作用。我可以确认在我的 Application 对象中广播意图之前会调用服务的 onCreate() 和 onStartCommand() 方法,但它似乎没有获得意图并执行相关工作。

任何帮助将不胜感激。

更新:

这是我从应用程序发送广播的方式(请注意,我首先启动服务):

 public class MyApplication extends Application {
        @Override
        public void onCreate() {
            Intent intent = new Intent(getApplicationContext(), MyService.class);
        getApplicationContext().startService(intent);
    getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

        }

 }

请注意,我在实际进行广播之前启动服务。该服务不会收到广播,但如果我从稍后启动的活动中执行类似的调用,它会收到广播。

I have a setup where I am running a background service in Android with an attached BroadcastReceiver listening for particular types of Intents. Those intents are then used by the broadcast receiver to call specific methods in the service. Below is code describing the structure of the service:

public class MyService extends Service {

     private class ServiceBroadcastReceiver extends BroadcastReceiver {


            private MyService getMyService() {
                return MyService.this;
            }

            public IntentFilter getASReceiverFilter() {
                IntentFilter filter = new IntentFilter()
                filter.addAction(Constants.ACTION_DO_SOMETHING);
                return filter;
            }

            @Override
            public void onReceive(Context context, Intent intent) {
                // TODO Auto-generated method stub
                MyService svc = getMyService();
                String intentAction = intent.getAction();
                Log.i(Constants.LOG_TAG, "Now trying to dispatch following action: " + intentAction);
                //Dispatch to the appropriate method in MyService. 
                if (intentAction.equals(AppServiceConstants.ACTION_DO_SOMETHING)) {
                    svc.doSomething();
                } 
            }
        }


    private ServiceBroadcastReceiver mRequestReceiver = new ServiceBroadcastReceiver();


    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }


    @Override
    public void onCreate() {

        Log.i(Constants.LOG_TAG, "Service Created!");
        //Register for broadcast messages indicating the add music button was pressed
        mRequestReceiver = new ServiceBroadcastReceiver();
       registerReceiver(mRequestReceiver, mRequestReceiver.getASReceiverFilter()); 
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.i(Constants.LOG_TAG, "Service Starting ... ");

        // If we get killed, after returning from here, restart
            return START_STICKY;
    }



    /***********************************************************************************
     * Service Dispatch Methods
     */
     protected void doSomething() {
         Log.i(Constants.LOG_TAG, "Doing something"); 
     }



}

My issue is with getting this service and its broadcast receiver to capture broadcasted intents from throughout my app. If I do something like the following ....

getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

.. it only works if I invoke that from within an Activity. However, I want to be able to "do something" even when the application first starts up, so I have put that statement in my own custom Application subclass in the onCreate() method, right after I create the MyService and start it up. For some reason, the broadcast is not working from within the Application class code when the app start up, but it will work if I put it in some code within an activity (eg in the onCreate() method of the activity). I can confirm that the service's onCreate() and onStartCommand() methods are being invoked prior to broadcasting the intent in my Application object, but it simply doesn't seem to get the intent and do the associated work.

Any help would be appreciated.

Update:

Here is how I send the broadcast from my application (note that I start the service first):

 public class MyApplication extends Application {
        @Override
        public void onCreate() {
            Intent intent = new Intent(getApplicationContext(), MyService.class);
        getApplicationContext().startService(intent);
    getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

        }

 }

Note that I'm starting the service before I actually do the broadcast. The service DOES NOT receive the broadcast, but if I do a similar call from an activity that I start up later, it does receive.

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

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

发布评论

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

评论(1

甜是你 2024-12-28 17:34:03

您的Application 是在流程中的任何其他组件之前创建的。因此,在 onCreate() 中,没有 Serivce 运行。如果您在调用应用程序的 onCreate() 时发送广播,则 Service 没有注册广播接收器,因为它甚至还没有创建。

因此,换句话说,您的服务没有收到广播通知,因为广播接收器尚未注册。它尚未注册,因为 Service 尚未启动。根据设计,它无法在 Application 的 onCreate() 返回之前启动。

您可以在应用程序的 onCreate() 中使用 Context.startService() 直接启动服务。您将能够通过 Intent 查找所有必需的数据。


更新问题的更新答案:

当您致电时:

getApplicationContext().startService(intent);

您要求 Android 稍后启动服务。该服务立即启动。预计稍后才开始。事实上,在您从应用程序的 onCreate() 函数返回之前,它肯定不会启动。这是因为所有 Service 的生命周期回调函数(例如 onCreate()onStart())都是从主 UI 线程调用的。 Applicaiton 的 onCreate 当前正在阻塞主 UI 线程。

因此,当您使用这些代码行发送广播时:

getApplicationContext().startService(intent);
getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

您实际上要求稍后启动服务,然后立即发送广播。因为服务甚至没有机会启动并注册此广播
通知,当它真正启动时,它不会收到任何东西。

您可以更改服务的 onStart() 代码来处理意图,然后使用以下命令启动服务:

Intent intent = new Intent(getApplicationContext(), MyService.class);
intent.setAction(Constants.ACTION_DO_SOMETHING);
getApplicationContext().startService(intent);

Your Application is created before any other component in the process. So in onCreate() there is no Serivce running. And if you send broadcast at the moment when Application's onCreate() is called, Service has no broadcast receiver registered because it wasn't even created.

So, in other words, you service is not receiving broadcast notification because broadcast receiver is not yet registered. And its not yet registered because Service is not yet started. And it can't be started before Application's onCreate() returns by design.

You can directly start service using Context.startService() from Application's onCreate(). You'll be able to path all the required data through Intent.


Updated answer to an updated question:

When you call:

getApplicationContext().startService(intent);

You ask Android to start service at some later time. The service is not started right away. It's only scheduled to start later. In fact it will definitely not start before you return from Application's onCreate() function. That's because all Service's lifecycle callback functions (like onCreate() and onStart()) are called from main UI thread. And Applicaiton's onCreate is currently blocking main UI thread.

So when you send broadcast using these lines of code:

getApplicationContext().startService(intent);
getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

You actually ask to start service at some later time, then immediately after that you send broadcast. And because service didn't even had chance to start and to register for this broadcast
notifications, it will not receive anything when it actually gets started.

You could change your service's onStart() code to handle the intent and then start service using:

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