Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 安卓第十三天筆記-服務(Service),安卓第十三天

安卓第十三天筆記-服務(Service),安卓第十三天

編輯:關於android開發

安卓第十三天筆記-服務(Service),安卓第十三天


安卓第十三天筆記-服務(Service)

Servcie服務

1.服務概念

服務

  • windows

服務沒有界面,一直運行在後台, 運行在獨立的一個進程裡面

  • android

服務沒有界面,一直運行在後台,默認是運行當前的應用程序進程裡面。

2.建立服務

  • 建立一個類繼承Service類

    public class ServiceDemo extends Service {
    
  • 在清單文件中注冊service

    <service android:name="com.ithiema.servicequick.servcie.ServiceDemo"></service>

     

3.生命周期

只會在開啟服務時初始化一次

    @Override
public void onCreate() {
    //只會在開啟服務時初始化一次
    super.onCreate();
}

 

每次開啟服務都會執行調用

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //每次開啟服務都會執行調用
    return super.onStartCommand(intent, flags, startId);
}

 

停止服務時,只執行一次

public void onDestroy() {
    //停止服務時,只執行一次
    super.onDestroy();
}

 

  • 完整生命周期

onCreate -- onStartCommand--onDestroy

  • 啟動多次服務

onCreate方法只會執行一次, 但是onStartCommand執行多次

  • 多次停止服務

只會執行一次onDestroy方法。

4.進程

Foreground process

前台進程: 當前與用戶進行交互的應用所處的進程

  • Visible process

可見進程: 應用程序不能交互,但是界面可見。 有點類似activity生命周期的onPause

  • Service process

服務進程: 應用程序裡面運行著一個服務

  • Background process

後台進程: 應用程序被最小化了(home)

  • Empty process

空進程:應用程序裡面沒有任何活動的組件(activity \ service)

前台進程 > 可見進程 > 服務進程 > 後台進程 > 空進程

5.開啟與停止服務

public void start(View v){
    startService(new Intent(this , ServiceDemo.class));
}


public void stop(View v){
    stopService(new Intent(this , ServiceDemo.class));
}

 

6.為什麼要使用服務

場景: 1. 在後台檢測設備接入狀況 2. 在後台執行聯網數據請求(類似股票軟件) 3. 音樂播放器

7.綁定服務第一種

Extending the Binder class 第一種

1 先寫一個繼承Service類

2.在Service中寫一個public類繼承Binder,在這個類中寫個方法返回具服務類的對象實例

3.在onBind 中返回 這個內部類的實例

4.在service中寫幾個public的方法提供給子類調用必須為public的

 /**
     * Created by  劉楠 on 2016-02-28 14:19.
     */
    public class LocalService extends Service {
        private static final String TAG = "LocalService";
        //聲明綁定的類
        private LocalBinder mBinder = new LocalBinder();
        //給客戶端使用
        private final Random mGenerator = new Random();

        /*
        第一種繼承Binder類
         */
        public class LocalBinder extends Binder {

            public LocalService getServcie() {
                Log.d(TAG, "==getServcie==");
                return LocalService.this;
            }

        }

        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG, "==IBinder==");
            return mBinder;
        }

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


        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d(TAG, "==onStartCommand==");
            return super.onStartCommand(intent, flags, startId);
        }

        /**
         * 返回一個隨機數
         *
         * @return
         */
        public int getRandom() {
            Log.d(TAG, "==getRandom==");
            return mGenerator.nextInt(500);
        }


        @Override
        public boolean onUnbind(Intent intent) {
            Log.d(TAG, "==onUnbind==");
            return super.onUnbind(intent);
        }

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

 

5.在Manifest.xml中注冊service

 <service android:name=".serivice.LocalService"/>

6.在客戶端的Activity中綁定service bindService(intnet,ServiceConnection,Context.BINDAUTOCREATE)

7.寫一個類實現ServiceConnection接口,在方法中完成獲取Service類的實例

8.調用服務中的方法

9.解除綁定

布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:onClick="bind1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="綁定服務1"/>


    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:onClick="show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="調用方法"/>

    <Button
        android:onClick="unBind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="解綁綁定服務1"/>
</LinearLayout>

 

客戶端類

        Activity

    /**
     * 綁定服務
     */
    public class MainActivity extends AppCompatActivity {
        private static final String TAG ="MainActivity" ;
        //服務
        private LocalService mService;

        private boolean mbound = false;

        private MyServiceConnection mConection;


        private TextView tv;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.d(TAG, "=====MainActivity==onCreate=====");

            tv = (TextView) findViewById(R.id.tv);
        }

        /**
         * 綁定服務
         * @param view 按鍵
         */
        public void bind1(View view){
            Log.d(TAG, "=====MainActivity==bind1=====");
            Intent intent = new Intent(this,LocalService.class);

            if(mConection==null){
                mConection = new MyServiceConnection();
            }

             mbound = bindService(intent, mConection, Context.BIND_AUTO_CREATE);

            Log.d(TAG, "=====MainActivity==flag=====" + mbound);


        }

        public   void show(View v) {

            if (mbound) {
                int random = mService.getRandom();
                tv.setText(random + "");
            }

        }


        /**
         * 服務連接類
         */
        private class MyServiceConnection implements  ServiceConnection{

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                LocalService.LocalBinder mBinder= (LocalService.LocalBinder) service;

                mService = mBinder.getServcie();
                Log.d(TAG, "=====MainActivity==MyServiceConnection==onServiceConnected===");


            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.d(TAG,"=====MainActivity==MyServiceConnection==onServiceDisconnected===");
                mbound=false;
            }
        }

        /**
         * 解除綁定
         * @param v
         */
        public  void unBind(View v){
            Log.d(TAG,"=====MainActivity==unBind======");
            if(mService!=null) {
                unbindService(mConection);
                mConection=null;

            }
        }

        /**
         * 銷毀
         */
        @Override
        protected void onDestroy() {
            Log.d(TAG,"=====MainActivity==onDestroy======");
            super.onDestroy();
            if(mService!=null&&mConection!=null) {
                unbindService(mConection);
                mConection=null;

            }
        }
    }

 

以上的方式如果只要給自己程序用同時不要把一些方法私有化的話都可以在Service中寫public的方法,使用這種方式

8.綁定服務第二種

使用Messenger與Handler的機制處理,這種方式是一種單線程的,不安全的,目前很少有人用了,會造成排隊現象

Service

    /**
 * Created by  劉楠 on 2016-02-28 16:29.
 */
public class MessengerService extends Service {

    public static final int MSG_SAY_HELLO = 1;

    Messenger mMessenger = new Messenger(new IncomingHandler());

    public class  IncomingHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){

                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(),"hello Android===handleMessage==",Toast.LENGTH_SHORT).show();


            }
        }
    }

    /**
     *
     * @param intent 意圖
     * @return
     */
    @Nullable //參數可以為空
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "===onBind====", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

 

清單文件

注冊
<service android:name=".service.MessengerService"/>

 

客戶端

    public class MainActivity extends AppCompatActivity {

        private Messenger mService;

        private MyServiceConnection mServiceConnection;

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

        /**
         * 界面可見時,綁定Service
         */
        @Override
        protected void onStart() {
            super.onStart();
            Intent intent = new Intent();
            intent.setClass(this, MessengerService.class);

            if(mServiceConnection==null){
                mServiceConnection = new MyServiceConnection();
            }
            //綁定
            bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        }

        private  class  MyServiceConnection implements  ServiceConnection{


            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {


                mService = new Messenger(service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }

        /**
         * 點擊事件
         * @param v
         */
        public void sayHello(View v) {

            Message msg = Message.obtain();
            msg.what=MessengerService.MSG_SAY_HELLO;
            //發送消息
            try {
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(mService!=null&&mServiceConnection!=null) {
                unbindService(mServiceConnection);
                mServiceConnection=null;
            }
        }
    }

 

9.使用普通接口完成

  • 使用接口的方式建立Service

接口

/**
 * Created by  劉楠 on 2016-02-28 18:25.
 * 接口定義方法讓Service中自定義的Binder來實現這個接口,同時調用Service中公用與私有方法
 */
    public interface IRemoteService {

        public void display(String name,int age);

        public void gogo();

    }

 

建立Service

    /**
     * Created by  劉楠 on 2016-02-28 18:20.
     */
    public class LocalService extends Service {
        //自定義的IBinder對象
        private LocalBinder mLocalBinder= new LocalBinder();


        /**
         * 自定義的Binder
         * 對面接頭的內線
         */
        public class LocalBinder extends Binder implements IRemoteService {
            //接口的方法
            @Override
            public void display(String name, int age) {
                //調用Service中的方法
                show(name,age);
            }
            //接口的方法
            @Override
            public void gogo() {
                //調用Service中的方法
                go();
            }
            //這裡算自定義的方法
            public void showData(){
                Toast.makeText(getApplicationContext(),new Date().toString(),Toast.LENGTH_SHORT).show();
            }
        }


        private static final String TAG ="LocalService" ;

        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG,"=====onBind=======");
            return mLocalBinder;
        }

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

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {

            Log.d(TAG,"=====onStartCommand=======");
            return super.onStartCommand(intent, flags, startId);
        }

        @Override
        public boolean onUnbind(Intent intent) {
            Log.d(TAG,"=====onUnbind=======");
            return super.onUnbind(intent);
        }

        @Override
        public void unbindService(ServiceConnection conn) {
            super.unbindService(conn);
            Log.d(TAG, "=====unbindService=======");
        }

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

        /*
                上面會調用這個方法
             */
        private void show(String name,int age){
            Toast.makeText(getApplicationContext(),"姓名:"+name+"年齡:"+age,Toast.LENGTH_SHORT).show();
            Log.d(TAG, "====service=show======");
        }

        /*
        上面的Binder會調用這個方法
         */

        private void go(){
            Toast.makeText(getApplicationContext(),"gogogogogogoggog",Toast.LENGTH_SHORT).show();
            Log.d(TAG, "====service=go======");
        }
    }

 

布局就5個按鍵

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="bind"
            android:text="綁定bindService服務"/>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="callMethod"
            android:text="調用服務中的方法"/>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="unBind"
            android:text="解除unBindService綁定"/>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="start"
            android:text="使用startService開始服務"/>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="stop"
            android:text="使用stopService停止服務"/>
    </LinearLayout>

 

Activity

public class MainActivity extends AppCompatActivity {
    private static final String TGA ="MainActivity" ;
    //連接的類
    private MyServcieConnection mConnection;
    //IBinder對象
    private LocalService.LocalBinder mLocalBinder;

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




    /**
     * 綁定服務
     *
     * @param view 按鍵
     */
    public void bind(View view) {
        Log.d(TGA, "========Activity===bind======");
        Intent intent = new Intent();

        intent.setClass(this, LocalService.class);
        if(mConnection==null){
            mConnection = new MyServcieConnection();
        }
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 調用服務中的方法
     *
     * @param view 按鍵
     */
    public void callMethod(View view) {
        Log.d(TGA,"========Activity===callMethod======");
        if(mLocalBinder!=null){
            //調用方法
            mLocalBinder.display("張三",18);
            mLocalBinder.gogo();
            mLocalBinder.showData();

        }
    }

    /**
     * 解除綁定服務
     *
     * @param view 按鍵
     */
    public void unBind(View view) {
        Log.d(TGA,"========Activity===unBind======");
        if(mConnection!=null){
            unbindService(mConnection);
            mConnection=null;
            mLocalBinder=null;
        }
    }

    /**
     * 開始服務
     *
     * @param view 按鍵
     */
    public void start(View view) {
        Log.d(TGA,"========Activity===start======");
        Intent intent = new Intent();
        intent.setClass(this, LocalService.class);
        startService(intent);
    }

    /**
     * 停止服務
     *
     * @param view 按鍵
     */
    public void stop(View view) {
        Log.d(TGA,"========Activity===stop======");
        //停止服務
        Intent intent = new Intent();
        intent.setClass(this, LocalService.class);
        stopService(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TGA, "========Activity===onDestroy======");
       /* if(mConnection!=null){
            unbindService(mConnection);
            mConnection=null;
            mLocalBinder=null;
            return;
        }
        //停止服務
        Intent intent = new Intent();
        intent.setClass(this, LocalService.class);
        stopService(intent);*/
    }

    /**
     * 服務連接類
     */
    private class MyServcieConnection implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TGA,"========Activity===onServiceConnected======");
            mLocalBinder = (LocalService.LocalBinder) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TGA,"========Activity===onServiceDisconnected======");
        }
    }
}

 

注冊

    <!--注冊-->
    <service android:name=".service.LocalService"/>

結果:

02-28 06:39:24.895 4350-4350/? D/MainActivity: ========Activity===bind======

02-28 06:39:24.968 4350-4350/? D/LocalService: =====onCreate=======
02-28 06:39:24.969 4350-4350/? D/LocalService: =====onBind=======
02-28 06:39:24.985 4350-4350/? D/MainActivity: ========Activity===onServiceConnected======
02-28 06:39:28.625 4350-4350/? D/MainActivity: ========Activity===callMethod======

02-28 06:39:28.631 4350-4350/? D/LocalService: ====service=show======
02-28 06:39:28.637 4350-4350/? D/LocalService: ====service=go======
ace 0xeb9b54a0, error=EGL_SUCCESS
02-28 06:39:30.906 4350-4350/? D/MainActivity: ========Activity===unBind======

02-28 06:39:30.937 4350-4350/? D/LocalService: =====onUnbind=======
02-28 06:39:30.937 4350-4350/? D/LocalService: =====onDestroy=======

02-28 06:39:32.721 4350-4368/? V/RenderScript: 0xe1f0e200 Launching thread(s), CPUs 4
02-28 06:39:35.827 4350-4350/? D/MainActivity: ========Activity===start======

02-28 06:39:35.846 4350-4350/? D/LocalService: =====onCreate=======
02-28 06:39:35.846 4350-4350/? D/LocalService: =====onStartCommand=======
02-28 06:39:36.878 4350-4350/? D/MainActivity: ========Activity===stop======

02-28 06:39:36.902 4350-4350/? D/LocalService: =====onDestroy=======

 

10.AIDL (AIDL-Android Interface Definition Language)

AIDL可以同時處理多個線程的請求,並且是線程安全的.

To use AIDL directly, you must create an .aidl file that defines the programming interface. The Android SDK tools use this file to generate an abstract class that implements the interface and handles IPC, which you can then extend within your service.

要使用AIDL必須建立一個擴展名為.aidl的文件,SDK會自動生成對象的抽象類同是實現接口與Handles IPC通信,在Service中可以選擇繼承

例如:支付寶,就只是暴露了,接口給商家使用,裡面具體怎麼實現並沒有暴露

將上面的接口後綴名改為.aidl

  • 更改Serive中的自定義IBinder

    public class LocalBinder extends IRemoteService.Stub {

  • 更改客戶端 中聲明不在寫原來的binder

       更改這個為
     private LocalService.LocalBinder mLocalBinder;
    

更改後

    //IRemoteService
    private IRemoteService mIRemoteService;

Activity

  public class MainActivity extends AppCompatActivity {
        private static final String TGA ="MainActivity" ;
        //連接的類
        private MyServcieConnection mConnection;
        //IRemoteService
        private IRemoteService mIRemoteService;

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




        /**
         * 綁定服務
         *
         * @param view 按鍵
         */
        public void bind(View view) {
            Log.d(TGA, "========Activity===bind======");
            Intent intent = new Intent();

            intent.setClass(this, LocalService.class);
            if(mConnection==null){
                mConnection = new MyServcieConnection();
            }
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }

        /**
         * 調用服務中的方法
         *
         * @param view 按鍵
         */
        public void callMethod(View view) {
            Log.d(TGA,"========Activity===callMethod======");
            if(mIRemoteService!=null){
                //調用方法
                try {
                    mIRemoteService.display("張三",18);
                    mIRemoteService.gogo();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }



            }
        }

        /**
         * 解除綁定服務
         *
         * @param view 按鍵
         */
        public void unBind(View view) {
            Log.d(TGA,"========Activity===unBind======");
            if(mConnection!=null){
                unbindService(mConnection);
                mConnection=null;
                mIRemoteService=null;
            }
        }

        /**
         * 開始服務
         *
         * @param view 按鍵
         */
        public void start(View view) {
            Log.d(TGA,"========Activity===start======");
            Intent intent = new Intent();
            intent.setClass(this, LocalService.class);
            startService(intent);
        }

        /**
         * 停止服務
         *
         * @param view 按鍵
         */
        public void stop(View view) {
            Log.d(TGA,"========Activity===stop======");
            //停止服務
            Intent intent = new Intent();
            intent.setClass(this, LocalService.class);
            stopService(intent);
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TGA, "========Activity===onDestroy======");

        }

        /**
         * 服務連接類
         */
        private class MyServcieConnection implements ServiceConnection{

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TGA,"========Activity===onServiceConnected======");
                mIRemoteService =IRemoteService.Stub.asInterface(service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.d(TGA,"========Activity===onServiceDisconnected======");
            }
        }
    }

 

這種aidl的方式只能調用Serivce接口中的方法,不能調用Service和自定義Binder中特有的方法 常用於給第三方的應用提供服務 * 通過

 IRemoteService.Stub.asInterface(service)

 

方法得到aidl定義的接口實例

11.startService與bindService的生命周期

  • startService與stopService

startService

        onCreate---創建服務時只執行一次
        onStartCommand  ----每次開啟服務都會調用

stopService

       onDestory--停止服務時多次調用,只會執行一次

*bindService與unBindServcie

bindService

    onCreate---創建服務時只執行一次
    onBind----多次調用,只執行一次

unBindService

    onUnbind----解除時,只執行一次
    onDestory----只執行一次

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved