1)start的方式与Service交互
Activity是不能很直接的与Service进行交互,需要借助与其它组件来完成。常见的就是利用广播接收器。Service发送广播,Activity接受广播。
2)bind的方式与Service交互
需要在Service中准备一个IBinder接口的实现类。将该实现类的对象作为onBind方法的返回值
在Activity中需要一个ServiceConnection对象,他会有两个回调方法,在其中一个方法中获得Service内onBind方法返回的IBinder对象。通过IB顶的人来实现与Service的交互。
3)AIDL的方式与Service交互(不常用)
Bind方式进行交互是有前提的,Activity和Service是出于同一个app中(同一个进程中)
通过AIDL可以实现跨进程的调用,一个APPA的Activity可以调用另一个APP的Service的方法
进行AIDL跨进程调用调用,必须使用Service的一个.aidl描述文件才可以进行
举例
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xxxx"
android:textSize="30sp"
android:background="#ffff0000"/>
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:text="Start"
android:onClick="start"/>
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/button1"
android:layout_marginTop="17dp"
android:text="Stop"
android:onClick="stop"/>`
Service代码:
初始化Handler handler = new Handler();//用于以秒为单位更新时间
在Service中重写onCreate和onDestroy方法
onCreate()中启动服务
onDestroy()中移除Handler;//Handler很强大,即使Service停止了,它任然在执行,所以要移除
package com.example.test01;
import java.text.SimpleDateFormat;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
Handler handler = new Handler();
public MyService() {
}
@Override
public void onCreate() {
Log.d("TAG", "服务创建");
super.onCreate();
handler.postDelayed(new Runnable() {
/**
* 当onCreate()执行,1秒后执行Runnable(),
* intent发送getServiceTime()的返回值,发送广播
*/
@Override
public void run() {
// TODO 发送广播,吧getServiveTime方法结果广播出去
Intent intent = new Intent("service_start");//随便写只要不重名
intent.putExtra("time", getServiceTime());
sendBroadcast(intent);
handler.postDelayed(this, 1000);//为了不让服务只更新一次而设置一个循环
}
}, 1000);//一秒更新一次
}
@Override
public void onDestroy() {
Log.d("TAG", "服务被销毁");
handler.removeCallbacksAndMessages(null);//点击结束Servier,然而handler还在工作
super.onDestroy();
}
public String getServiceTime(){
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");//设置要得到系统的分秒
return sdf.format(System.currentTimeMillis());
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Activity代码:
onResume()中使用过滤器得到Service发送的广播并注册广播接收器,
onPause()中注销广播接收器
package com.example.test01;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tvTime;
MyReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTime = (TextView) findViewById(R.id.textView1);
}
@Override
protected void onResume() {
super.onResume();
receiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("service_start");//从系统底层获得这条广播
registerReceiver(receiver, filter);//注册广播接收器
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);//退出时注销广播接收器
}
/**启动服务**/
public void start(View v){//按钮的点击属性,启动服务
Intent intent = new Intent(this,MyService.class);
startService(intent);
}
/**关闭服务**/
public void stop(View v){//按钮的点击属性,停止服务
Intent intent = new Intent(this,MyService.class);
stopService(intent);
}
/**广播接收类*/
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();//得到Service发送的广播
if("service_start".equals(action)){
//从intent中,包“时间”取出来,放到tvTime中显示
String time = intent.getStringExtra("time");
tvTime.setText(time);
}
}
}
}
2.bind的方式与Service交互
绑定方式的xml根启动模式的xml差别不大,把按钮从启动改为绑定(bind),停止改为解绑(unbind)
Service代码:
package com.example.servicedemo;
import java.text.SimpleDateFormat;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
Handler handler = new Handler();
public MyService() {
}
@Override
public void onCreate() {
Log.d("TAG", "服务创建");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TAG", "服务启动");
return super.onStartCommand(intent, flags, startId);//返回的是Service的一种类型
}
@Override
public void onDestroy() {
Log.d("TAG", "服务被销毁");
handler.removeCallbacksAndMessages(null);//点击结束Servier,然而handler还在工作
super.onDestroy();
}
/**
* 提供当前时间
* @return
*/
public String getServiceTime(){
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
return sdf.format(System.currentTimeMillis());
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public class MyBinder extends Binder{
public String getTime(){
return getServiceTime();
}
}
}
Activity代码:
package com.example.servicedemo;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.widget.TextView;
import com.example.servicedemo.MyService.MyBinder;
public class MainActivity extends Activity {
TextView tvTime;
/***Bind方式***/
ServiceConnection conn;
MyBinder binder;
Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTime = (TextView) findViewById(R.id.textView1);
handler = new Handler();
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyBinder) service;
handler.postDelayed(new Runnable() {
@Override
public void run() {
tvTime.setText(binder.getTime());
handler.postDelayed(this, 1000);
}
}, 1000);
}
};
}
public void bind(View v){
Intent intent = new Intent(this,MyService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
public void unbind(View v){
unbindService(conn);
handler.removeCallbacksAndMessages(null);
}
}
3.AIDL的方式与Service交互
这是一种跨进程的交互方式一个APP的Activity可以调用另一个App中Service的方法
创建两个app,一个叫服务提供方,一个服务提供方
*两个app中都必须有一个相同名字的包,包里必须要有一个一样的aidl文件
*必须是服务提供方先启动,服务提供方才能使用提供方的服务
先创建服务提供方xml布局都一样,就不说了,提供方的
包名:com.example.serviceprovider(使用方也要创建一个这样的包名)
不要忘了包下的aidl文件,
提供方->MyBinder代码:
我怕写错,所以代码是我创建一个接口,然后删除“public”后,复制黏贴过来的,最后把接口删出就好
package com.example.serviceprovider;
interface MyBinder {
String getTime();
}
提供方->Service代码:
package com.example.serviceprovider;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return new MyBinderImpl();
}
public String getServiceTime(){
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
return sdf.format(new Date());
}
public class MyBinderImpl extends MyBinder.Stub{
@Override
public String getTime() throws RemoteException {
// TODO Auto-generated method stub
return getServiceTime();
}
}
}
提供方->Activity代码:(这代码并没有什么卵用)
package com.example.serviceprovider;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
使用方的aidl文件是复制过来的,新建一个包含它的包
使用方->Activity代码:
package com.exampleserviceuser;
import com.example.serviceprovider.MyBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.TextView;
/**
* 复制aidl文件,包名一样
* @author Android
*
*/
public class MainActivity extends Activity {
TextView tvTime;
Handler handler;
ServiceConnection conn;
MyBinder binder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTime = (TextView) findViewById(R.id.textView1);
handler = new Handler();
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//不能强转,Stub是交给系统处理的
binder = MyBinder.Stub.asInterface(service);
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
tvTime.setText(binder.getTime());
handler.postDelayed(this, 1000);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 1000);
}
};
}
public void bind(View v){
//通过隐式意图启动远程Sercice
Intent intent = new Intent("com.tarena.REMOTE_TIME_SERVICE");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
public void unbind(View v){
unbindService(conn);
handler.removeCallbacksAndMessages(null);
}
}
源码下载:Service的三种简单交互方式