Activity和Service通信

来源:互联网 发布:小约翰 震惊 知乎 编辑:程序博客网 时间:2024/05/02 01:04

一.概述

Service是一个应用程序组件,它能够在后台执行一些耗时较长的操作,并且不提供用户界面。服务能被其它应用程序的组件启动,即使用户切换到另外的应用时还能保持后台运行。此外,应用程序组件还能与服务绑定,并与服务进行交互,甚至能进行进程间通信(IPC)。 比如,服务可以处理网络传输、音乐播放、执行文件I/O、或者与content provider进行交互,所有这些都是后台进行的。

在Activity中,启动服务有两种方式,startService和bindService,首先让我们看看这两种方式下服务的生命周期图:

这里写图片描述

二.Activity向Service传值

(1)当我们通过startService启动服务的时候,从生命周期图我们可以看到会调用Service的startCommand方法
我们启动服务是通过intent启动的,可以把参数放到intent里面

Intent service = new Intent(this,ProgressService.class);        service.putExtra("name","main");        startService(service);

然后

@Override    public int onStartCommand(Intent intent, int flags, int startId) {        String name = intent.getStringExtra("name");        return super.onStartCommand(intent, flags, startId);    }

(2)通过bindService方式启动服务,通过生命周期图我们可以看到会调用
Service的unBind方法,同理

@Override    public IBinder onBind(Intent intent) {        String name = intent.getStringExtra("name");        Toast.makeText(this,"name"+name,Toast.LENGTH_SHORT).show();        return new ProgressBinder();    }

三.Service向Activity通信

(1)通过Binder对象

当我们通过bindService启动一个Service的时候,会传入一个ServiceConnection对象,当服务连接成功后,回传回来一个IBinder类型的对象,通过这个对象,Service就可以和Activity通信。

举一个例子:

public class MainActivity extends Activity {    private ProgressBar progressBar;    private ProgressService progressService;    private int progress = 0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        progressBar = (ProgressBar) findViewById(R.id.progressBar);        Intent service = new Intent(this,ProgressService.class);        //绑定服务        bindService(service, connection, Context.BIND_AUTO_CREATE);    }    public void bindService(View view){        //开始下载        progressService.startDownload();        //更新进度        changeProgress();    }    ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //当服务连接成功后,获得返回的Binder对象            ProgressBinder binder = (ProgressBinder) service;            //通过binder获得服务对象,这样我们就可以调用服务里面的方法了            progressService = binder.getService();        }    };    /**     * 每隔1秒去检查进度     */    public void changeProgress(){        new Thread(){            @Override            public void run() {                super.run();                while (progress<=ProgressService.MAX_PROGRESS){                    //获取服务中更新后的进度                    progress = progressService.getProgress();                    progressBar.setProgress(progress);                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }.start();    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(connection);    }}
/** * 更新进度的服务 */public class ProgressService extends Service{    public static final int MAX_PROGRESS = 100;    public int progress;    @Override    public IBinder onBind(Intent intent) {        return new ProgressBinder();    }    class ProgressBinder extends Binder{        //给外部提供一个方法,获得当前服务的对象        public ProgressService getService(){            return ProgressService.this;        }    }    public int getProgress(){        return progress;    }    /**     * 模拟下载操作     */    public void startDownload(){        new Thread(){            @Override            public void run() {                super.run();                while (progress<=MAX_PROGRESS) {                    progress+=10;                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }.start();    }}

效果图如下:

这里写图片描述

在上面的代码中,我们每次都要主动调用getProgress方法来获取最新的进度,有没有感觉有点被动呢,那么有没有主动一点的方法,这个时候可以利用回调。直接上代码

public class MainActivity extends Activity {    private ProgressBar progressBar;    private ProgressService progressService;    private int progress = 0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        progressBar = (ProgressBar) findViewById(R.id.progressBar);        Intent service = new Intent(this,ProgressService.class);        //绑定服务        bindService(service, connection, Context.BIND_AUTO_CREATE);    }    public void bindService(View view){        progressService.startDownload();        progressService.setOnProgressChangedListener(new ProgressService.OnProgressChangedListener() {            @Override            public void onProgressChanged(int progress) {                progressBar.setProgress(progress);            }        });    }    ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //当服务连接成功后,获得返回的Binder对象            ProgressBinder binder = (ProgressBinder) service;            //通过binder获得服务对象,这样我们就可以调用服务里面的方法了            progressService = binder.getService();        }    };    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(connection);    }}
public class ProgressService extends Service{    public static final int MAX_PROGRESS = 100;    public int progress;    OnProgressChangedListener listener;    interface OnProgressChangedListener{        void onProgressChanged(int progress);    }    public void setOnProgressChangedListener(OnProgressChangedListener listener){        this.listener = listener;    }    @Override    public IBinder onBind(Intent intent) {        return new ProgressBinder();    }    class ProgressBinder extends Binder{        //给外部提供一个方法,获得当前服务的对象        public ProgressService getService(){            return ProgressService.this;        }    }    /**     * 模拟下载操作     */    public void startDownload(){        new Thread(){            @Override            public void run() {                super.run();                while (progress<=MAX_PROGRESS) {                    progress+=10;                    try {                        listener.onProgressChanged(progress);                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }.start();    }}

(2)利用广播

public class MainActivity extends Activity {    private ProgressBar progressBar;    private ProgressService progressService;    private int progress = 0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        progressBar = (ProgressBar) findViewById(R.id.progressBar);        Intent service = new Intent(this,ProgressService.class);        //绑定服务        bindService(service, connection, Context.BIND_AUTO_CREATE);        //添加过滤器,用于过滤发送过来广播        IntentFilter filter = new IntentFilter("intent.action.update");        //注册广播        registerReceiver(new ProgressReceiver(),filter);    }    public void bindService(View view){        //开始下载        progressService.startDownload();    }    ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //当服务连接成功后,获得返回的Binder对象            ProgressBinder binder = (ProgressBinder) service;            //通过binder获得服务对象,这样我们就可以调用服务里面的方法了            progressService = binder.getService();        }    };    class ProgressReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            //获取发送过来的进度信息            int progress = intent.getIntExtra("progress", 0);            progressBar.setProgress(progress);        }    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(connection);    }}
public class ProgressService extends Service{    public static final int MAX_PROGRESS = 100;    public int progress;    @Override    public IBinder onBind(Intent intent) {        return new ProgressBinder();    }    class ProgressBinder extends Binder{        //给外部提供一个方法,获得当前服务的对象        public ProgressService getService(){            return ProgressService.this;        }    }    /**     * 模拟下载操作     */    public void startDownload(){        new Thread(){            @Override            public void run() {                super.run();                while (progress<=MAX_PROGRESS) {                    progress+=10;                    try {                        Intent intent  = new Intent("intent.action.update");                        intent.putExtra("progress",progress);                        sendBroadcast(intent);                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }.start();    }}

最后总结一下:

Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法

Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好

0 0