在写有关推送的代码,用的长连接的方式。
具体逻辑:登录时 启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不断的向外发送广播,应用接收广播并更新心跳数据(假设需要更新的数据是这个),缺点就是广播是低效且不稳定,易受系统监控影响,有可能丢失某一些时刻的广播数据,不过简单,容易实现,对数据不严格要求可以考虑使用这个方式;
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对象。