安卓Service基础

版权声明:本文为博主原创文章,未经博主允许不得转载。转载请注明出处。 https://blog.csdn.net/qq_36882793/article/details/83309507

以下:内容部分取自菜鸟教程:http://www.runoob.com/w3cnote/android-tutorial-service-1.html),内容仅用于自我记录学习使用。

Service分为两种启动方式,StartService和BindService。
Service本身还是在UI线程中,因此如果需要进行耗时操作仍需要开辟线程。

其生命周期如下图:

在这里插入图片描述

onCreate() : 当Service被创建时回调该方法,整个Service声明周期仅调用一次。onDestory()同理.
onStartCommand(intent,flag,startId) : 当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!
IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!
onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!

**StartService 方式启动Service:

启动会创建一个Service实例  --- > onCreate	 ---- > onStartCommand() ---> stopService()  ---> onDestory()。 当再次调用StartService时并不会创建新的Service实例,而是调用原先Service的onStartCommand() 方法。
StartService 启动方式和调用者无关,即使调用者被销毁,只要不调用stopService() 方法就无法停止Service服务。同时不论启动多少次Service,调用一次stopService即可全部停止。

BindService方式启动Service:

  1. 启动时会创建一个Service实例 —> onCreate —> onBind() 。然后调用者可以通过IBinder和Service进行交互了。当再次使用bindService时,并不会在调用onCreate和onBind。只会直接把IBinder对象传递给其他后来增加的客户端!
  2. 解除与服务的绑定,只需调用unbindService(),此时onUnbind和onDestory方法将会被调用!这是一个客户端的情况,假如是多个客户端绑定同一个Service的话,情况如下 当一个客户完成和service之间的互动后,它调用 unbindService() 方法来解除绑定。当所有的客户端都和service解除绑定后,系统会销毁service。
  3. bindService模式下的Service是与调用者相互关联的,可以理解为 “一条绳子上的蚂蚱”,要死一起死,在bindService后,一旦调用者销毁,那么Service也立即终止!
  4. bindService(Intent Service,ServiceConnection conn,int flags)解析:
    service:通过该intent指定要启动的Service
    conn :ServiceConnection对象,用户监听访问者与Service间的连接情况, 连接成功回调该对象中的onServiceConnected(ComponentName,IBinder)方法; 如果Service所在的宿主由于异常终止或者其他原因终止,导致Service与访问者间断开 连接时调用onServiceDisconnected(CompanentName)方法,主动通过unBindService() 方法断开并不会调用上述方法!
    flags:指定绑定时是否自动创建Service(如果Service还未创建), 参数可以是0(不自动创建),BIND_AUTO_CREATE(自动创建)。

先StartService后BindService启动方式:

如果Service已经由某个客户端通过StartService()启动,接下来由其他客户端 再调用bindService()绑定到该Service后调用unbindService()解除绑定最后在 调用bindService()绑定到Service的话,此时所触发的生命周期方法如下:
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )
前提是:onUnbind()方法返回true!!! 这里或许部分读者有疑惑了,调用了unbindService后Service不是应该调用 onDistory()方法么!其实这是因为这个Service是由我们的StartService来启动的 ,所以你调用onUnbind()方法取消绑定,Service也是不会终止的!
得出的结论: 假如我们使用bindService来绑定一个启动的Service,注意是已经启动的Service!!! 系统只是将Service的内部IBinder对象传递给Activity,并不会将Service的生命周期 与Activity绑定,因此调用unBindService( )方法取消绑定时,Service也不会被销毁!

以下:

StartService启动方式与Activity实时信息交互:(不推荐启动模式下的交互)
onCreate -->onStartCommand

   /**
     *  start方式启动Service
     */
    private void startService(){
        Intent intent = new Intent(getApplicationContext(), DownLoadStartService.class);
        // 可以通过这种方式给Service传值
        Bundle bundle = new Bundle();
        bundle.putString("key", "传值内容");
        intent.putExtra("bundle", bundle);

        startService(intent);
    }

public class DownLoadStartService extends Service{

    private final static String TAG = DownLoadIntentService.class.getSimpleName();

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 在这里执行操作
            }
        };
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override   // start 启动方式不调用
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return null;
    }

    @Override   // stopService时调用
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }
}

  1. 广播方式:
package com.example.qxb_810.downloadservicedemo;


import android.app.Service;
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.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;

import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
import com.example.qxb_810.downloadservicedemo.service.DownLoadBindService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadIntentService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadStartService;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {
    private final static String TAG = MainActivity.class.getSimpleName();


    @BindView(R.id.btn_begin)
    Button btnBegin;
    @BindView(R.id.btn_pause)
    Button btnPause;
    @BindView(R.id.btn_stop)
    Button btnStop;

    private int mCurrProgress = 0;

    // Broadcast
    private LocalBroadcastManager mLocalBroadcastManager;
    private DownloadReceiver mReceiver;
    private IntentFilter mFilter;
    private Intent mIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        regisiterBroadcast();
    }

    /**
     * 注册广播
     */
    private void regisiterBroadcast() {
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
        mReceiver = new DownloadReceiver();
        mFilter = new IntentFilter();
        mFilter.addAction(DownloadReceiver.ACTION_REFRESH);
        mLocalBroadcastManager.registerReceiver(mReceiver, mFilter);
    }

    /**
     * 取消广播
     */
    private void unregisiterBroadcast() {
        mLocalBroadcastManager.unregisterReceiver(mReceiver);
    }


    @OnClick(R.id.btn_begin)
    public void beginClick() {
        startService();
    }


    /**
     * start方式启动Service
     */
    private void startService() {
        mIntent = new Intent(getApplicationContext(), DownLoadStartService.class);
        // 可以通过这种方式给Service传值
        Bundle bundle = new Bundle();
        bundle.putString("key", "传值内容");
        mIntent.putExtra("bundle", bundle);

        startService(mIntent);
    }

    @OnClick(R.id.btn_pause)
    public void pauseClick() {
        stopService(mIntent);
    }

    @OnClick(R.id.btn_stop)
    public void stopClick() {
        stopService(mIntent);
    }

    @Override
    protected void onDestroy() {
        mLocalBroadcastManager.unregisiterBroadcast();
        super.onDestroy();
    }

    /**
     * 广播接收者
     */
    public class DownloadReceiver extends BroadcastReceiver {
        public final static String ACTION_REFRESH = "refresh_progress"; // 更新进度条事件

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_REFRESH)) {
                mCurrProgress = intent.getIntExtra("progress", mCurrProgress);
                btnBegin.setText("正在下载..." + mCurrProgress + "%");
            }
        }
    }
}

package com.example.qxb_810.downloadservicedemo.service;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.example.qxb_810.downloadservicedemo.MainActivity;
import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;

public class DownLoadStartService extends Service{

    private final static String TAG = DownLoadIntentService.class.getSimpleName();

    private int mCurrProgress = 0;
    private Handler mHandler = new Handler();

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            // 在这里执行操作
            // 当连接成功后赋值
            if (mCurrProgress >= 100){
                mHandler.removeCallbacks(this);
            }else {
                mCurrProgress += 1;
                // 发送广播

                Intent intent = new Intent(MainActivity.DownloadReceiver.ACTION_REFRESH);
                intent.putExtra("progress", mCurrProgress);
                LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
                mHandler.postDelayed(this, 1000);
            }
        }
    };
    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        mHandler.postDelayed(mRunnable, 1000);
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override   // start 启动方式不调用
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return null;
    }

    @Override   // stopService时调用
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }
}

BindService启动方式与Activity实时信息交互:

  1. 接口回调方式:
package com.example.qxb_810.downloadservicedemo;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;

import com.example.qxb_810.downloadservicedemo.intfaces.DownLoadInteface;
import com.example.qxb_810.downloadservicedemo.service.DownLoadBindService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadIntentService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadStartService;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity{
    private final static String TAG = MainActivity.class.getSimpleName();
    
    @BindView(R.id.btn_begin)
    Button btnBegin;
    @BindView(R.id.btn_pause)
    Button btnPause;
    @BindView(R.id.btn_stop)
    Button btnStop;

    private DownLoadBindService.MyBinder myBinder;
    private ServiceConnection mConnection;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        
        mConnection = new ServiceConnection() {
            @Override   // service连接成功时回调
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.e(TAG, "连接成功");
                myBinder = (DownLoadBindService.MyBinder)service;   // 获取Binder类
                myBinder.setDownLoadInteface(new DownLoadInteface() {
                    @Override
                    public void setCurrProgress(int progress) {
                        btnBegin.setText("正在下载..." + progress + "%");
                    }
                });
            }

            @Override   // service连接断开时回调
            public void onServiceDisconnected(ComponentName name) {
                Log.e(TAG, "连接断开");
            }
        };

    }

    @OnClick(R.id.btn_begin)
    public void beginClick() {
        bindService();
    }

    /**
     * bind方式启动Service
     */
    private void bindService() {
        Intent intent = new Intent(getApplicationContext(), DownLoadBindService.class);
        // 可以通过这种方式给Service传值
        Bundle bundle = new Bundle();
        bundle.putString("key", "传值内容");
        intent.putExtra("bundle", bundle);

        bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
    }



    /**
     *  bind方式启动IntentService
     */
    private void bindIntentService(){
        Intent intent = new Intent(getApplicationContext(), DownLoadIntentService.class);
        // 可以通过这种方式给Service传值
        Bundle bundle = new Bundle();
        bundle.putString("key", "传值内容");
        intent.putExtra("bundle", bundle);

        bindService(intent, mConnection, Service.BIND_AUTO_CREATE);

    }


    @OnClick(R.id.btn_pause)
    public void pauseClick() {
        unbindService(mConnection);
    }

    @OnClick(R.id.btn_stop)
    public void stopClick() {
        unbindService(mConnection);
    }
}

package com.example.qxb_810.downloadservicedemo.service;

import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import com.example.qxb_810.downloadservicedemo.intfaces.DownLoadInteface;

public class DownLoadBindService extends Service {
    private final static String TAG = DownLoadBindService.class.getSimpleName();

    private int mCurrProgress = 0;
    private MyBinder myBinder = new MyBinder();
    private Handler mHandler = new Handler();
    private Runnable mRunable = new Runnable() {
        @Override
        public void run() {
            // 当连接成功后赋值
            if (myBinder.getDownLoadInteface() != null) {
                mCurrProgress += 1;
                myBinder.getDownLoadInteface().setCurrProgress(mCurrProgress);      // 通知Activity数据更新
            }
            if (mCurrProgress >= 100){
                mHandler.removeCallbacks(this);
            }else {
                mHandler.postDelayed(this, 1000);
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
    }

    // 自定义Binder类,提供暴露给Activity的方法  --- 这里暴露接口
    public class MyBinder extends Binder {
        DownLoadInteface downLoadInteface;

        public DownLoadInteface getDownLoadInteface() {
            return downLoadInteface;
        }

        public void setDownLoadInteface(DownLoadInteface downLoadInteface) {
            this.downLoadInteface = downLoadInteface;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        mHandler.postDelayed(mRunable, 1000);
        return myBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind");
        mHandler.removeCallbacks(mRunable);
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }
}

  1. 广播方式:
package com.example.qxb_810.downloadservicedemo;


import android.app.Service;
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.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;

import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
import com.example.qxb_810.downloadservicedemo.service.DownLoadBindService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadIntentService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadStartService;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity{
    private final static String TAG = MainActivity.class.getSimpleName();


    @BindView(R.id.btn_begin)
    Button btnBegin;
    @BindView(R.id.btn_pause)
    Button btnPause;
    @BindView(R.id.btn_stop)
    Button btnStop;

    private int mCurrProgress = 0;

        // Service
    private DownLoadBindService.MyBinder myBinder;
    private ServiceConnection mConnection;

    // Broadcast
    private DownloadReceiver mReceiver;
    private IntentFilter mFilter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        regisiterBroadcast();

        mConnection = new ServiceConnection() {
            @Override   // service连接成功时回调
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.e(TAG, "连接成功");
            }

            @Override   // service连接断开时回调
            public void onServiceDisconnected(ComponentName name) {
                Log.e(TAG, "连接断开");
            }
        };

    }

    /**
     *  注册广播
     */
    private void regisiterBroadcast(){
        mReceiver = new DownloadReceiver();
        mFilter = new IntentFilter();
        mFilter.addAction(DownloadReceiver.ACTION_REFRESH);
        registerReceiver(mReceiver, mFilter);
    }

    /**
     *  取消广播
     */
    private void unregisiterBroadcast(){
        mLocalBroadcastManager.unregisterReceiver(mReceiver);
    }


    @Override
    protected void onDestroy() {
        unregisiterBroadcast();
        super.onDestroy();
    }

    @OnClick(R.id.btn_begin)
    public void beginClick() {
        bindService();
    }


    /**
     * bind方式启动Service
     */
    private void bindService() {
        Intent intent = new Intent(getApplicationContext(), DownLoadBindService.class);
        // 可以通过这种方式给Service传值
        Bundle bundle = new Bundle();
        bundle.putString("key", "传值内容");
        intent.putExtra("bundle", bundle);

        bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
    }

    @OnClick(R.id.btn_pause)
    public void pauseClick() {
        unbindService(mConnection);
    }

    @OnClick(R.id.btn_stop)
    public void stopClick() {
        unbindService(mConnection);
    }

    /**
     *  广播接收者
     */
    public class DownloadReceiver extends BroadcastReceiver {
        public final static String ACTION_REFRESH = "refresh_progress"; // 更新进度条事件

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_REFRESH)){
                mCurrProgress = intent.getIntExtra("progress", mCurrProgress);
                btnBegin.setText("正在下载..." + mCurrProgress + "%");
            }
        }
    }
}

package com.example.qxb_810.downloadservicedemo.service;

import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import com.example.qxb_810.downloadservicedemo.MainActivity;
import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
import com.example.qxb_810.downloadservicedemo.intfaces.DownLoadInteface;

public class DownLoadBindService extends Service {
    private final static String TAG = DownLoadBindService.class.getSimpleName();

    private int mCurrProgress = 0;
    private MyBinder myBinder = new MyBinder();
    private Handler mHandler = new Handler();
    private Intent intent = new Intent(DownloadReceiver.ACTION_REFRESH);
    private Runnable mRunable = new Runnable() {
        @Override
        public void run() {
            // 当连接成功后赋值
            if (mCurrProgress >= 100){
                mHandler.removeCallbacks(this);
            }else {
                mCurrProgress += 1;
                // 发送广播
                intent.putExtra("progress", mCurrProgress);
                sendBroadcast(intent);
                mHandler.postDelayed(this, 1000);
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
    }

    // 自定义Binder类,提供暴露给Activity的方法
    public class MyBinder extends Binder {

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        mHandler.postDelayed(mRunable, 1000);
        return myBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind");
        mHandler.removeCallbacks(mRunable);
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }
}

注意:
1. IntentService中onHandleIntent方法必须重写,在这个方法里单独开辟了新的线程,可以在里面执行耗时操作。IntentService也是一个Service,可通过start或者bind方式启动,需要注意的是,bind启动方式不会走onHandlerIntent方法,只执行onCreate和onBind方法,BindService启动方式果要实时更新数据需要通过接口回调或者广播方式。IntentService执行完任务后自动销毁。多个任务时将排队进行。

  1. Service 需要在AndroidManifest.xml注册,如下:
<service
            android:name=".service.DownLoadIntentService"
            android:exported="false">
            <intent-filter>
                <action android:name="DownLoadIntentService" />
            </intent-filter>
  </service>

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/83309507