Activity和Service通信

一.概述

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值