如何使用 PendingIntent 从服务到客户端/活动进行通信?

发布于 2024-11-09 09:01:27 字数 668 浏览 0 评论 0原文

我一直在 Android 开发者网站上阅读以下文本,特别是在 Framework 下主题->服务->启动服务

其中规定如下:

如果服务不提供绑定,则使用 startService() 传递的意图是应用程序组件和服务之间的唯一通信模式。但是,如果您希望服务发回结果,那么启动服务的客户端可以为广播创建一个 PendingIntent(使用 getBroadcast()),并将其传递到启动服务的 Intent 中的服务。然后,该服务可以使用广播来传递结果。

我对此有几个问题:

  1. 此文本是否都适用于 ServiceIntentService
  2. 如何(按代码方式)从 Service 内实现这一点; 然后,服务可以使用广播来传递结果。并且提到的广播将在哪里将结果传递给原始客户端/活动?是否有一些方法应该被覆盖(例如 onActivityResult())或其他方法?

I have been reading the following text on the Android Developers Site, specifically under the Framework Topics -> Services -> Starting a Service.

There it states the following :

If the service does not also provide binding, the intent delivered with startService() is the only mode of communication between the application component and the service. However, if you want the service to send a result back, then the client that starts the service can create a PendingIntent for a broadcast (with getBroadcast()) and deliver it to the service in the Intent that starts the service. The service can then use the broadcast to deliver a result.

I have a couple of questions regarding this :

  1. Does this text both apply to Services and IntentServices ?
  2. How (codewise) should this be achieved from within the Service; The service can then use the broadcast to deliver a result. and also where would the mentioned broadcast deliver the result to the original client/activity? Is there some method that should be overwritten (like onActivityResult()) or something?

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

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

发布评论

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

评论(3

余生一个溪 2024-11-16 09:01:27

Question was asked few months ago, but in case anyone is still looking for answer I hope I can help.

在下面的示例中,我们有本地服务,负责执行一些耗时的操作。 Activity 向服务发出请求,但不绑定到服务 - 只是通过请求发送意图。此外,Activity 还包含 BroadcastReceiver 的信息,当服务完成所请求的任务时,应回调该信息。该信息通过 PendingIntent 传递。该服务在后台线程中处理任务,当任务完成时,服务会向 BroadcastReceiver 广播一个答案。

1.创建BroadcastReceiver子类:

public class DataBroadcastReceiver extends BroadcastReceiver {
   static Logger log = LoggerFactory.getLogger(DataRequestService.class);   
   @Override
   public void onReceive(Context context, Intent intent) {
      log.info(" onReceive");
   }
}

当任务完成时,该广播接收器将从服务中收到通知。

2.创建服务

public class DataRequestService extends Service {

   private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
         super(looper);
      }

      @Override
      public void handleMessage(Message msg) {
         log.info("handleMessage");
         //... performing some time-consuming operation         
         Bundle bundle = msg.getData();
         PendingIntent receiver = bundle.getParcelable("receiver");
         // Perform the operation associated with PendingIntent
         try {            
            //you can attach data from the operation in the intent.
            Intent intent = new Intent();
            Bundle b = new Bundle();
            //b.putString("key", value);
            intent.putExtras(b);
            receiver.send(getApplicationContext(), status, intent);
         } catch (CanceledException e) {         
         e.printStackTrace();
         }         
      }
   }
   
   @Override
   public void onStart(Intent intent, int startId) {
      Bundle bundle = intent.getExtras();
      Message msg = mServiceHandler.obtainMessage();
      msg.setData(bundle);
      mServiceHandler.sendMessage(msg);
   }

嗯,最重要的部分是在handleMessage()方法中。服务只是进行广播操作,将结果传递给广播接收器。

3.您还需要在 Manifest.xml 中注册您的广播接收器和服务

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ramps.servicetest"
    android:versionCode="1"
    android:versionName="1.0" >
   ....
       <service android:name=".service.DataRequestService" android:exported="false"/>
       <receiver android:name=".service.DataBroadcastReceiver"></receiver>
    </application>
</manifest><br>

4。最后,从 Activity 向您的服务发出请求:

Intent serviceIntent = new Intent(context, DataRequestService.class);   
   @Override
   public void onClick(View v) {
      //this is the intent that will be broadcasted by service.
      Intent broadcastReceiverIntent = new Intent(context, DataBroadcastReceiver.class);      
      //create pending intent for broadcasting the DataBroadcastReceiver
      PendingIntent pi = PendingIntent.getBroadcast(context, 0, broadcastReceiverIntent, 0);      
      Bundle bundle = new Bundle();            
      bundle.putParcelable("receiver", pi);
      //we want to start our service (for handling our time-consuming operation)
      Intent serviceIntent = new Intent(context, DataRequestService.class);
      serviceIntent.putExtras(bundle);
      context.startService(serviceIntent);
   }

5.对原始客户/活动做出响应。

您可以拥有抽象活动,您的所有活动都将从该抽象活动中扩展。此抽象活动可以自动将自身注册/注销为广播接收器中的响应侦听器。实际上这里没有太多选项,但重要的是,如果您保留对活动的静态引用,那么您必须在活动被销毁时删除该引用。

问候,
坡道

Question was asked few months ago, but in case anyone is still looking for answer I hope I can help.

In the example below we have local service, responsible for performing some time-consuming operations. Activity makes the requests to the service, but does not bind to it - just sends the intent with request. Additionally, Activity includes the information of BroadcastReceiver that should be called back when service is done with the requested task. The information is passed by PendingIntent. The service handles the task in background thread and when task is finished, service broadcasts the BroadcastReceiver with an answer.

1. Create BroadcastReceiver subclass:

public class DataBroadcastReceiver extends BroadcastReceiver {
   static Logger log = LoggerFactory.getLogger(DataRequestService.class);   
   @Override
   public void onReceive(Context context, Intent intent) {
      log.info(" onReceive");
   }
}

This broadcast receiver will be notified from service, when task is done.

2. Create Service

public class DataRequestService extends Service {

   private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
         super(looper);
      }

      @Override
      public void handleMessage(Message msg) {
         log.info("handleMessage");
         //... performing some time-consuming operation         
         Bundle bundle = msg.getData();
         PendingIntent receiver = bundle.getParcelable("receiver");
         // Perform the operation associated with PendingIntent
         try {            
            //you can attach data from the operation in the intent.
            Intent intent = new Intent();
            Bundle b = new Bundle();
            //b.putString("key", value);
            intent.putExtras(b);
            receiver.send(getApplicationContext(), status, intent);
         } catch (CanceledException e) {         
         e.printStackTrace();
         }         
      }
   }
   
   @Override
   public void onStart(Intent intent, int startId) {
      Bundle bundle = intent.getExtras();
      Message msg = mServiceHandler.obtainMessage();
      msg.setData(bundle);
      mServiceHandler.sendMessage(msg);
   }

Well, the most important part is in handleMessage() method. Service simply makes the broadcasts operation for delivering results to Broadcast Receiver.

3. You also need to register your broadcast receiver and service in Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ramps.servicetest"
    android:versionCode="1"
    android:versionName="1.0" >
   ....
       <service android:name=".service.DataRequestService" android:exported="false"/>
       <receiver android:name=".service.DataBroadcastReceiver"></receiver>
    </application>
</manifest><br>

4. And finally, make request to your service from Activity:

Intent serviceIntent = new Intent(context, DataRequestService.class);   
   @Override
   public void onClick(View v) {
      //this is the intent that will be broadcasted by service.
      Intent broadcastReceiverIntent = new Intent(context, DataBroadcastReceiver.class);      
      //create pending intent for broadcasting the DataBroadcastReceiver
      PendingIntent pi = PendingIntent.getBroadcast(context, 0, broadcastReceiverIntent, 0);      
      Bundle bundle = new Bundle();            
      bundle.putParcelable("receiver", pi);
      //we want to start our service (for handling our time-consuming operation)
      Intent serviceIntent = new Intent(context, DataRequestService.class);
      serviceIntent.putExtras(bundle);
      context.startService(serviceIntent);
   }

5. Delivering response to original client/activity.

You can have abstract activity from which all your activities will be extending. This abstrct activity can automatically register/deregister itself as a response listener in broadcast receiver. Not many options here actually, but it is important that if you keep static references to your activity then you must remove the refernece when activity is destroyed.

Regards,
Ramps

長街聽風 2024-11-16 09:01:27

正如此处所写

服务和 Activity 之间的通信可以使用
PendingIntent.为此我们可以使用
createPendingResult().createPendingResult() 创建一个新的 PendingIntent 对象,您可以将其交给服务使用和发送
结果数据返回到 onActivityResult(int, int,
Intent) 回调。因为 PendingIntent 是 Parcelable ,并且可以
因此被放入一个 Intent extra 中,你的 Activity 可以通过这个
服务的 PendingIntent。服务反过来可以调用 send()
PendingIntent 上的方法通过以下方式通知活动
事件的 onActivityResult。

活动

公共类 PendingIntentActivity 扩展了 AppCompatActivity
{
@覆盖
protected void onCreate(@Nullable Bundle savingInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PendingIntent 待定结果 = createPendingResult(
100、新的Intent(), 0);
Intent意图 = new Intent(getApplicationContext(), PendingIntentService.class);
Intent.putExtra(“pendingIntent”,pendingResult);
启动服务(意图);

}

@覆盖
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode==200) {
Toast.makeText(this,data.getStringExtra("名称"),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

服务

public class PendingIntentService 扩展服务 {

    私人静态最终字符串[]项目= {“lorem”,“ipsum”,“dolor”,
            “坐”,“amet”,“consectetuer”,“adipiscing”,“elit”,“morbi”,
            “vel”、“ligula”、“vitae”、“arcu”、“aliquet”、“mollis”、“etiam”、
            “vel”,“erat”,“placerat”,“ante”,“porttitor”,“sodales”,
            “pellentesque”、“augue”、“purus”};
    私有 PendingIntent 数据;

    @覆盖
    公共无效 onCreate() {
        super.onCreate();
    }

    @覆盖
    公共int onStartCommand(Intent意图,int标志,int startId){

        数据 = Intent.getParcelableExtra("pendingIntent");

        新的LoadWordsThread().start();
        返回START_NOT_STICKY;
    }

    @覆盖
    公共 IBinder onBind(Intent 意图) {
        返回空值;
    }

    @覆盖
    公共无效onDestroy(){
        super.onDestroy();
    }

    类 LoadWordsThread 扩展线程 {
        @覆盖
        公共无效运行(){
            for(字符串项目:项目){
                if (!isInterrupted()) {

                    意图结果 = new Intent();
                    result.putExtra("名称", 项目);
                    尝试 {
                        data.send(PendingIntentService.this,200,结果);
                    } catch (PendingIntent.CanceledException e) {

                        e.printStackTrace();
                    }
                    系统时钟.睡眠(400);

                }
            }
        }
    }
}

As written here

Communication between service and Activity can be done using
PendingIntent.For that we can use
createPendingResult().createPendingResult() creates a new PendingIntent object which you can hand to service to use and to send
result data back to your activity inside onActivityResult(int, int,
Intent) callback.Since a PendingIntent is Parcelable , and can
therefore be put into an Intent extra,your activity can pass this
PendingIntent to the service.The service, in turn, can call send()
method on the PendingIntent to notify the activity via
onActivityResult of an event.

Activity

public class PendingIntentActivity extends AppCompatActivity
{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PendingIntent pendingResult = createPendingResult(
100, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), PendingIntentService.class);
intent.putExtra("pendingIntent", pendingResult);
startService(intent);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode==200) {
Toast.makeText(this,data.getStringExtra("name"),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

Service

public class PendingIntentService extends Service {

    private static final String[] items= { "lorem", "ipsum", "dolor",
            "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
            "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
            "vel", "erat", "placerat", "ante", "porttitor", "sodales",
            "pellentesque", "augue", "purus" };
    private PendingIntent data;

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

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

        data = intent.getParcelableExtra("pendingIntent");

        new LoadWordsThread().start();
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class LoadWordsThread extends Thread {
        @Override
        public void run() {
            for (String item : items) {
                if (!isInterrupted()) {

                    Intent result = new Intent();
                    result.putExtra("name", item);
                    try {
                        data.send(PendingIntentService.this,200,result);
                    } catch (PendingIntent.CanceledException e) {

                        e.printStackTrace();
                    }
                    SystemClock.sleep(400);

                }
            }
        }
    }
}
新雨望断虹 2024-11-16 09:01:27

为了在服务活动之间进行通信。您还可以使用官方 Android 示例中提到的 Binder
http://developer.android.com/reference/android/app/ Service.html#LocalServiceSample

有关详细说明,请参阅此答案
https://stackoverflow.com/a/36983011/4754141

In order to perform communication between service and activity. You can also use Binder as mentioned in Official Android Example
http://developer.android.com/reference/android/app/Service.html#LocalServiceSample

For detail explanation see this answers
https://stackoverflow.com/a/36983011/4754141

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