我一直在Android开发者网站上阅读以下文字,特别是在Framework Topics -> Services -> Starting a Service下。
它说明了以下内容:
如果服务不提供绑定,则startService()提供的意图是应用程序组件与服务之间唯一的通信方式。但是,如果您希望服务返回结果,则启动服务的客户端可以为广播创建PendingIntent(使用getBroadcast())并将其传递给启动服务的Intent中的服务。然后,该服务可以使用广播来传递结果。
我对此有几个问题:
Service
s 和 IntentService
?Service
内实现这一目标; 然后,服务可以使用广播来传送结果。以及所提到的广播将结果传送到原始客户端/活动的位置?是否有一些方法应该被覆盖(如onActivityResult()
)或其他什么?答案 0 :(得分:45)
几个月前问了一个问题,但是如果有人还在寻找答案,我希望我能提供帮助。
在下面的示例中,我们有本地服务,负责执行一些耗时的操作。 Activity向服务发出请求,但不绑定它 - 只是通过请求发送intent。此外,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();
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。提供对原始客户/活动的响应。
您可以使用抽象活动来扩展您的所有活动。此abstrct活动可以自动注册/注销自身作为广播接收器中的响应侦听器。实际上这里的选项并不多,但重要的是,如果您对活动保持静态引用,则必须在活动被销毁时删除引用。
的问候,
斜坡
答案 1 :(得分:0)
为了在服务和活动之间进行通信。您也可以使用官方Android示例中提到的Binder http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
有关详细说明,请参阅此答案 https://stackoverflow.com/a/36983011/4754141
答案 2 :(得分:0)
写成here
服务和活动之间的通信可以使用 PendingIntent.For我们可以使用 createPendingResult() .createPendingResult()创建一个新的PendingIntent对象,您可以将其交给服务使用和发送 结果数据返回到onActivityResult内的活动(int,int, Intent)callback.Since PendingIntent是Parcelable,并且可以 因此,加入一个额外的Intent,你的活动可以通过这个 PendingIntent to service。服务反过来可以调用send() PendingIntent上的方法通过通知活动 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); } } } } }