27

我一直在 Android Developers Site 上阅读以下文本,特别是在Framework Topics -> Services -> Starting a Service下。

在那里它陈述了以下内容:

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

我对此有几个问题:

  1. 此文本是否同时适用于Services IntentServices ?
  2. 应该如何(代码方面)从内部实现这一点Service然后服务可以使用广播来传递结果。以及提到的广播将结果传递给原始客户/活动的地方?是否有一些方法应该被覆盖(比如onActivityResult())或什么?
4

3 回答 3

49

几个月前提出了问题,但如果有人仍在寻找答案,我希望我能提供帮助。

在下面的示例中,我们有本地服务,负责执行一些耗时的操作。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. 响应原始客户/活动

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

问候,
坡道

于 2011-11-06T18:59:01.057 回答
0

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

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

于 2016-05-02T12:50:25.857 回答
0

如此处所写

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

活动

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

服务

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

                }
            }
        }
    }
}
于 2018-03-06T10:58:16.590 回答