今天晚上把service的用法整理一下,service在Android中的地位僅次于activity,其重要性可見一斑。下面主要從四個部分分别講解:
分别是startService,bindservice(兩個基礎用法。通過log檢視生命周期)messenger和aidl(Android IPC機制主要也是通過service與binder來實作的)
編寫activityInfo類來管理這四個測試的activity類,友善activity之間的跳轉,簡化代碼
package com.example.servicetest;
public class ActivityInfo
{
private String name;
private Class clazz;
public ActivityInfo(String name, Class clazz)
{
super();
this.name = name;
this.clazz = clazz;
}
public String getName()
{
return name;
}
public Class getClazz()
{
return clazz;
}
public void setName(String name)
{
this.name = name;
}
public void setClazz(Class clazz)
{
this.clazz = clazz;
}
}
測試主類 MainActivity代碼:
package com.example.servicetest;
import java.util.Arrays;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class MainActivity extends Activity
{
private ListView mListView;
private final List<ActivityInfo> mData = Arrays.asList(new ActivityInfo(
"StartService", ActivityStartService.class), new ActivityInfo(
"bindService", ActivityBindService.class), new ActivityInfo(
"Menssenger", ActivityMessenger.class), new ActivityInfo("aidl",
ActivityAidl.class));
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化view,個人的風格而已
initView();
}
private void initView()
{
mListView = (ListView) findViewById(R.id.lv_activity_main);
//為listview設定adapter
mListView.setAdapter(new MyAdapter(this, mData));
mListView.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3)
{
Intent intent = new Intent();
//通過前面設計的activityInfo得到要跳轉的activity的class
intent.setClass(MainActivity.this, mData.get(arg2).getClazz());
startActivity(intent);
}
});
}
}
listView的adapter實作很簡單,繼承自baseAdapter,使用viewholder去優化listview,想必大家都了解。
(1)通過startService(Intent intent)的方式開啟服務
package com.example.servicetest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityStartService extends Activity implements OnClickListener
{
private Button mButtonStart, mButtonStop;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.service_layout);
initView();
}
private void initView()
{
mButtonStart = (Button) findViewById(R.id.btn_start_service);
mButtonStop = (Button) findViewById(R.id.btn_stop_service);
mButtonStart.setOnClickListener(this);
mButtonStop.setOnClickListener(this);
}
@Override
public void onClick(View arg0)
{
switch (arg0.getId())
{
case R.id.btn_start_service:
//開啟service
startService(new Intent(ActivityStartService.this,
StartService.class));
break;
//停止service
case R.id.btn_stop_service:
stopService(new Intent(ActivityStartService.this,
StartService.class));
break;
default:
break;
}
}
}
service的實作:
package com.example.servicetest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class StartService extends Service
{
private final String TAG = "StartService";
@Override
public void onCreate()
{
Log.e(TAG, "-----oncreate----");
super.onCreate();
}
@Override
public void onDestroy()
{
Log.e(TAG, "-----onDestroy----");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e(TAG, "----onStartCommand----");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0)
{
Log.e(TAG, "----onBind----");
return null;
}
@Override
public void onRebind(Intent intent)
{
Log.e(TAG, "----onReBind----");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent)
{
Log.e(TAG, "----onUnbind----");
return super.onUnbind(intent);
}
}
(2)bindService的啟動過程,需要注意的是通過bindService啟動service時,當service正常結束的時候,是不會調用onServiceDisconnected方法的,即使手動調用了unBindService()方法。
package com.example.servicetest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityBindService extends Activity implements OnClickListener
{
private Button mButtonBind, mButtonUnBind;
private final String TAG = "ActivityBindService";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.service_layout);
initView();
}
private void initView()
{
mButtonBind = (Button) findViewById(R.id.btn_start_service);
mButtonUnBind = (Button) findViewById(R.id.btn_stop_service);
mButtonBind.setOnClickListener(this);
mButtonUnBind.setOnClickListener(this);
}
@Override
public void onClick(View arg0)
{
switch (arg0.getId())
{
case R.id.btn_start_service:
bindService(
new Intent(ActivityBindService.this, StartService.class),
mConnection, BIND_AUTO_CREATE);
break;
case R.id.btn_stop_service:
unbindService(mConnection);
break;
default:
break;
}
}
private final ServiceConnection mConnection = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName arg0)
{
Log.e(TAG, "----onServiceDisconnected----");
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1)
{
Log.e(TAG, "----onServiceConnected----");
}
};
}
(3)messenger使用service進行IPC通信:
messenger主要是使用了Ibinder機制,其本質也是使用了aidl,但是他的好處是不用手工編寫aidl檔案,也不用理會aidl的生成過程。使用麼三messege 和 Handler進行消息進行傳遞通信。因為handler是線程安全而且是一對一的通信,是以當Android IPC是一對一的時候,可以考慮使用messenger代替aidl去實作程序間通信
package com.example.servicetest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityMessenger extends Activity implements OnClickListener
{
private final String TAG = "ActivityMessenger";
private Button mButton, mButton2;
private Messenger iMessenger;
private final Handler mHandler = new Handler(new Callback()
{
@Override
public boolean handleMessage(Message arg0)
{
switch (arg0.what)
{
case RemoteService.MSG_FROM_CLIENT:
String msg = arg0.getData().getString("rsp");
Log.e(TAG, msg);
break;
default:
break;
}
return false;
}
});
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.service_layout);
initView();
}
private void initView()
{
mButton = (Button) findViewById(R.id.btn_start_service);
mButton.setOnClickListener(this);
mButton2 = (Button) findViewById(R.id.btn_stop_service);
mButton2.setOnClickListener(this);
}
@Override
public void onClick(View arg0)
{
switch (arg0.getId())
{
case R.id.btn_start_service:
bindService(
new Intent(ActivityMessenger.this, RemoteService.class),
mConnection, BIND_AUTO_CREATE);
break;
case R.id.btn_stop_service:
unbindService(mConnection);
break;
default:
break;
}
}
private final ServiceConnection mConnection = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName arg0)
{
Log.e(TAG, "----onServiceDisconnected----");
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1)
{
Log.e(TAG, "----onServiceConnected----");
//初始化messenger
iMessenger = new Messenger(arg1);
//設定message的類型
Message message = Message.obtain(null,
RemoteService.MSG_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg", "msg from client");
message.setData(bundle);
//這一句很重要,表明該消息的回複消息處理的handler為上面定義的mHandler。
message.replyTo = new Messenger(mHandler);
try
{
iMessenger.send(message);
} catch (RemoteException e)
{
e.printStackTrace();
}
}
};
}
下面看看RemoteService類:
package com.example.servicetest;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
public class RemoteService extends Service
{
public static final int MSG_FROM_CLIENT = ;
private final String TAG = "RemoteService";
private Messenger iMessenger;
private final Handler mHandler = new Handler(new Callback()
{
@Override
public boolean handleMessage(Message arg0)
{
switch (arg0.what)
{
case RemoteService.MSG_FROM_CLIENT:
//獲得服務程序傳遞過來的msg
String msg = arg0.getData().getString("msg");
Log.e(TAG, msg);
/**
*注意前面設定過msg的replyTo為用戶端定義的mHandler
*/
iMessenger = arg0.replyTo;
Bundle bundle = new Bundle();
bundle.putString("rsp", "rsp from server");
Message message = Message.obtain(null,
RemoteService.MSG_FROM_CLIENT);
message.setData(bundle);
try
{
iMessenger.send(message);
} catch (RemoteException e)
{
e.printStackTrace();
}
break;
default:
break;
}
return false;
}
});
@Override
public IBinder onBind(Intent arg0)
{
return new Messenger(mHandler).getBinder();
}
}
(4)最後就是aidl方式,aidl是處理Android程序間通信的,可以實作一對多的通信,下面通過一個相加求和的例子來講解
下面是aidl檔案,在兩個app項目中,需要設定包名一模一樣,會在gen包下生成對應的Java檔案
package com.example.servicetest;
/**
*注意書寫規範
*interface 沒有 public private 的修飾
*方法也沒有public private的修飾
*/
interface AIDLSum{
double sum(double d1, double d2);
}
package com.example.servicetest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityAidl extends Activity implements OnClickListener
{
private Button mButton;
private final String TAG = "ActivityAidl";
private AIDLSum mAidlService;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.service_layout);
initView();
}
private void initView()
{
mButton = (Button) findViewById(R.id.btn_start_service);
mButton.setOnClickListener(this);
}
@Override
public void onClick(View arg0)
{
switch (arg0.getId())
{
case R.id.btn_start_service:
bindService(new Intent(ActivityAidl.this, AIDLService.class),
mConnection, BIND_AUTO_CREATE);
break;
default:
break;
}
}
private final ServiceConnection mConnection = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName arg0)
{
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1)
{
Log.e(TAG, "----onServiceConnected----");
//asInterface函數可以在gen的aidl對應的java檔案中檢視
mAidlService = AIDLSum.Stub.asInterface(arg1);
double sum;
try
{
sum = mAidlService.sum(, );
Log.e(TAG, sum + "");
} catch (RemoteException e)
{
e.printStackTrace();
}
}
};
@Override
protected void onDestroy()
{
super.onDestroy();
unbindService(mConnection);
};
}
最後看看AIDLService.java檔案:
package com.example.servicetest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class AIDLService extends Service
{
private final String TAG = "AIDLService";
@Override
public IBinder onBind(Intent arg0)
{
Log.e(TAG, "----onBind----");
return stub;
}
//這裡是處理邏輯的核心部分,就是實作了aidl中的interface中的接口函數
private final AIDLSum.Stub stub = new AIDLSum.Stub()
{
@Override
public double sum(double d1, double d2) throws RemoteException
{
return d1 + d2;
}
};
}
以上就是service的四種使用場景。希望有所幫助
————————————–向死而生———————————
梅花香自苦寒來