Service-IntentService&Service-AIDL進程間通信

什麼是Service-IntentService?

IntentService 是繼承自 Service 並處理異步請求的一個類,在 IntentService內有一個工作線程來處理耗時操作,當任務執行完後,IntentService 會自動停止,不需要我們去手動結束,可以看做是Service和HandlerThread的結合體,在完成了使命之後會自動停止,適合需要在工作線程處理UI無關任務的場景,如果啓動 IntentService 多次,那麼每一個耗時操作會以工作隊列的方式在 IntentService 的 onHandleIntent 回調方法中執行,依次去執行,使用串行的方式,執行完自動結束。

優與劣

優勢:不需要開啓線程
劣勢:使用廣播向activity傳值

案例演示

使用IntentService網絡請求json串,將json串使用廣播發送給activity界面:

步驟:創建服務、註冊服務、啓動服務

MainActivity:

public class MainActivity extends AppCompatActivity {
    private  MyReceiver myReceiver;
    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //註冊廣播
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("com.bawei.intentservice");
        myReceiver=new MyReceiver();
        registerReceiver(myReceiver,intentFilter);
        //開啓服務
        intent=new Intent(this,MyIntentService.class);
        startService(intent);


    }
    //解除廣播+關閉服務
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);
        stopService(intent);
    }

    class MyReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String action=intent.getAction();
            if("com.bawei.intentservice".equals(action)){
                Bundle bundle = intent.getExtras();
                String json = bundle.getString("json", "");
                //接續json串 展現在ListView 中
                Toast.makeText(context, ""+json, Toast.LENGTH_SHORT).show();

            }
        }
    }
}

Service:

public class MyIntentService extends IntentService {
    //TODO  注意:必須提供無參數構造,不然清單文件中註冊報錯
    public MyIntentService(){
        super("MyIntentService");
    }

    public MyIntentService(String name) {
        super(name);
    }
    //TODO  將所有耗時操作都在該方法中完成,相當於開啓線程
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        StringBuffer sb=new StringBuffer();
        HttpURLConnection connection=null;
        InputStream inputStream=null;
        try {
            URL url=new URL("http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&page=1");
            connection = (HttpURLConnection) url.openConnection();
            connection.setReadTimeout(5*1000);
            connection.setConnectTimeout(5*1000);

            if(connection.getResponseCode()==200){
                inputStream  = connection.getInputStream();
                byte[] b=new byte[1024];
                int len=0;
                while((len=inputStream.read(b))!=-1){
                    sb.append(new String(b,0,len));
                }
                //TODO 向Activity或Fragment發送json串
                Intent intent1=new Intent();
                intent1.setAction("com.bawei.intentservice");
                Bundle bundle = new Bundle();
                bundle.putString("json",sb.toString());
                intent1.putExtras(bundle);
                sendBroadcast(intent1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                connection.disconnect();
            }
        }
    }
}

什麼是Service-AIDL?

AIDL,全稱是Android Interface Define Language,即安卓接口定義語言,可以實現安卓設備中進程之間的通信(Inter Process Communication, IPC)
安卓中的服務分爲兩類:
本地服務(例如:網絡下載大文件,音樂播放器,後臺初始化數據庫的操作)
遠程服務(例如:遠程調用支付寶進程的服務)

使用步驟

服務端:

創建AIDL文件
修改aidl文件,提供一個方法,該方法 就是處理客戶端的請求
rebuild project之後會發現自動生成一個Java文件:IMyAidlInterface.java
在服務端中新建一個類,繼承Service,在其中定義一個IBinder類型的變量iBinder,引用上述接口IMyAidlInterface.java類中的Stub類對象,實現其中的add方法,在Service的onBind方法中,返回iBinder變量
清單文件中註冊SErverService服務,在註冊時應設置exported屬性爲true,保證該Service能被其他應用調用,否則會報java.lang.SecurityException: Not allowed to bind to service Intent 異常

客戶端:

在客戶端創建同樣AIDL文件,要求包名AIDL名字必須一致,內容也必須一樣提供add方法,rebuild 項目
綁定服務調用服務器進程的方法

先啓動服務端,再啓動客戶端

public class ServerService extends Service {
    //TODO 代理人
    IBinder binder=new IMyAidlInterface.Stub() {
        @Override
        public int add(int num1, int num2) throws RemoteException {
            return num1+num2;
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
}
public class MainActivity extends AppCompatActivity {
    IMyAidlInterface iMyAidlInterface;
    //3.綁定服務回調
    private ServiceConnection connection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //綁定服務成功後,返回服務端返回的binder,將其轉成IMyAidlInterface調用add方法
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                int num=iMyAidlInterface.add(4,6);//調用服務端的add方法並得到結果
                Toast.makeText(MainActivity.this, ""+num, Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            //解除綁定時調用, 清空接口,防止內容溢出
            iMyAidlInterface=null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //1.綁定服務
        Intent intent=new Intent();
        intent.setAction("com.bawei.1609A");//設置action
        intent.setPackage("com.example.aidl_server");//設置服務端應用進程包名
        bindService(intent,connection, Service.BIND_AUTO_CREATE);
    }
    //2.解除綁定
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章