在写有关推送的代码,用的长连接的方式。
具体逻辑:登录时 启service,service中启一个线程,线程中构建一个CommunicateManegr对象,此对象里面有一个BlockingDeque双端队列处理包的顺序问题, 还有若干线程分别处理心跳包、登录包、推送消息、其它业务消息、断线重连、心跳检测等操作。
初次运行程序,长连接建立起来;然后退出系统,为了保持长连接,后台服务仍运行。再次运行程序时,需要判断后台服务是否仍在运行,仍在运行的话,需要取出之前运行的service对象,添加一些登录包。
这里的取出之前运行的service对象,如何取出?
不局限与取出之前运行的service对象的问题,是否从一开始 我关于长连接的处理逻辑就有一些理解不当的地方?
伪代码:
class MyService extends Service{
public CommnicateManager cManager;
@Override
public void onCreate() {
new Thread(new Runnable() {
@Override
public void run() {
CommunicateManager manager = CommunicateManager.getInstance();
cManager = manager;
manager.connect();
manager.add(LoginPackage);//添加登录包
manager.add(registerPackage);//添加注册包
manager.startHeardBeatThread();//开启心跳线程
manager.startCommunicate();//开启其它线程
}
}.start();
}
}
public class LoginActivtiy extends BaseActivity implements OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.login:
if (isServiceWork(LoginActivtiy.this,"com.example.service")){//判断第一次运行的服务是否存在
//TODO: 需要得到第一次运行的服务对象service 如何得到??? manager.add(loginPackage)
}else{
startService(myService);
}
break;
default:
break;
}
}
//判断某个服务是否正在运行的方法
public boolean isServiceWork(Context mContext, String serviceName) {
boolean isWork = false;
ActivityManager myAM = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> myList = myAM.getRunningServices(200);
// List<RunningAppProcessInfo> apps = myAM.getRunningAppProcesses();
if (myList.size() <= 0) {
return false;
}
for (int i = 0; i < myList.size(); i++) {
String mName = myList.get(i).service.getClassName().toString();
if (mName.equals(serviceName)) {
isWork = true;
break;
}
}
return isWork;
}
}
阿神2017-04-17 16:29:03
既然是想要長連接,就要service常駐後台,因此,bindService方式是不可行的。你需要一個remote service,使用startService方式,把心跳服務獨立於應用之外,至於應用和remote service之間的通信,可有兩種方式,Broadcast和IPC。
Broadcast
,讓你的remote service不斷的向外發送廣播,應用接收廣播並更新心跳數據(假設需要更新的數據是這個),缺點就是廣播是低效且不穩定,易受系統監控影響,有可能遺失某一些時刻的廣播數據,不過簡單,容易實現,對數據不嚴格要求可以考慮使用這個方式;Broadcast
,让你的remote service不断的向外发送广播,应用接收广播并更新心跳数据(假设需要更新的数据是这个),缺点就是广播是低效且不稳定,易受系统监控影响,有可能丢失某一些时刻的广播数据,不过简单,容易实现,对数据不严格要求可以考虑使用这个方式;
IPC
IPC
,即AIDL方式,如果你對AIDL熟悉,強烈建議你使用這個來實現與remote service的通信,如果不熟悉,會有一定難度,不過就當學習吧,屬於Android高階知識,後來也是會有很大幫助的。
🎜
🎜至於你想取得Service對象,確實不太準確,並沒有service本身的API能告知使用者service對像是否存在。可以換個思路,在前面開啟remote service的前提下,可以使用ActivityManager來查詢應用進程,匹配remote service進程名,進程名存在,則remote service存在。大體上只提供了一些思路,具體實作還需要你去找資料完善了。 🎜PHP中文网2017-04-17 16:29:03
Service的啟動方式,除了StartService還有BindService。
這樣啟動Service。
bindService(Intent service, ServiceConnection conn,int flags);
這是一個conn物件。
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//TODO 这里就得到了service对象
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
當然你還要在Service裡面複寫Onbind,這個方法會回傳一個Ibinder對象,裡麵包含著Service對象。