検索

ホームページ  >  に質問  >  本文

长连接 - android 如何取得正在运行的service对象

在写有关推送的代码,用的长连接的方式。
具体逻辑:登录时 启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;
    }
}
巴扎黑巴扎黑2773日前696

全員に返信(3)返信します

  • 阿神

    阿神2017-04-17 16:29:03

    長時間の接続が必要なため、サービスをバックグラウンドに常駐させる必要があるため、bindService メソッドは実行できません。ハートビートサービスをアプリケーションから独立させるには、リモートサービスが必要です。 アプリケーションとリモートサービス間の通信には、ブロードキャストとIPCの2つの方法があります。

    • Broadcast では、リモート サービスが継続的に外部にブロードキャストを送信し、アプリケーションがそのブロードキャストを受信して​​ハートビート データを更新します (更新する必要があるデータがこれであると仮定します)。欠点は次のとおりです。ブロードキャストは非効率的で、不安定で、システム監視の影響を受けて、特定の瞬間にブロードキャスト データが失われる可能性がありますが、実装はシンプルで簡単です。データに関する厳密な要件がない場合は、この方法の使用を検討できます。

    • IPC これは AIDL メソッドです。AIDL に精通している場合は、これを使用してリモート サービスと通信することを強くお勧めします。 、しかしそれを学ぶだけでAndroidに属します 高度な知識も将来的に役立ちます。

    Service オブジェクトを取得したいのですが、サービス オブジェクトが存在するかどうかをユーザーに伝えるサービス自体の API はありません。リモート サービスが以前に有効になっているという前提で、ActivityManager を使用してアプリケーション プロセスをクエリし、プロセス名が存在する場合はリモート サービスのプロセス名を照合することができます。一般的に、これはいくつかのアイデアを提供するだけです。特定の実装では、情報を検索して改善する必要があります。

    返事
    0
  • 怪我咯

    怪我咯2017-04-17 16:29:03

    bindservice

    返事
    0
  • PHP中文网

    PHP中文网2017-04-17 16:29:03

    サービスの起動メソッドには、StartService と BindService があります。

    このようにサービスを開始します。

    リーリー

    これは conn オブジェクトです。

    リーリー

    もちろん、Service で Onbind をオーバーライドする必要があります。このメソッドは、Service オブジェクトを含む Ibinder オブジェクトを返します。

    返事
    0
  • キャンセル返事