2015-12-14 3 views
5

私のアプリは本質的に、メインで実行されるソケットサーバーの検出を有効にする目的でNSDサービス(Bonjourサービス)を時々登録する必要があるバックグラウンドサービスですバックグラウンドサービス(別名アプリで実行)。Android:親プロセスの実行後に残っているBonjourサービスを停止するabplbtly

私が正しくAndroid Bonjour Service docを読んでいた場合、これはあなたが(簡潔にするため省略)Bonjourサービスを開始する方法です:

mNsdManager = Context.getSystemService(Context.NSD_SERVICE); 
mDiscoveryListener = new NsdManager.DiscoveryListener() 
mNsdManager.discoverServices(
     SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); 

を...これは、あなたがそれを止める方法です:

mNsdManager.unregisterService(mRegistrationListener); 

ここで私の頭を包み込むことはできません:メインサービスが急にダウンした場合、クラッシュ時に登録されたBonjourサービスは、もは​​や目的がなくても稼働し続けますverはもはや周囲にありません)。

mRegistrationListenerサービスが最初に登録されているため、メインサービスが再起動されたときにゾンビサービスをクリーンアップできません。

私は間違ったアプローチをとっていると思われます。メインサービスがクラッシュした後、ゾンビの混乱を残さないようにするにはどうすればよいですか?Bonjourサービスが遅れていますか?

答えて

1

アンドロイドボンジュールへの非特異的、あなたはここで答えに概説されているとしてあなたのサービスを設定することにより、クラッシュを処理しようとすることができます:あなたはunregisterService呼び出しを行うために、これを設定することができない場合Can I call a method before my application go to crash

、 ActivityManagerのAPI killBackgroundProcessesを使用するように設定する必要があります。これはあなたのマニフェストに権限を追加する必要があります。私が正しく、メインサービス(サーバソケットと一つに)あなたを理解している場合、レジスタ/ Nsdサービスを登録解除バックグラウンドサービスを開始している間

android.permission.KILL_BACKGROUND_PROCESSES 
+0

私はメインプロセス内でBonjourサービスを実行する方法を望んでいましたが、UncaughtExceptionHandlerを使用してキャッチされていない例外をキャッチするのはおそらく方法です(Androidの実装ではこのオプションが許可されていないのは驚きです) 。あなたの答えを受け入れるでしょう。次の数日の間に何もうまくいかなければ。 – Hugo

+0

私は同意する、それを処理する適切な方法があると思います。理論をサポートするためのドキュメントは見つかりませんでしたが、OSによって処理される可能性があります。 Googleは人々がまったくそれをやろうとは思わないかもしれないと考えているかもしれないので、自動的にそれを処理する必要があります。 –

+0

「UncaughtExceptionHandler」を使って私のために働いたサービスを登録解除しました。(サービスが登録されて数秒後に別のスレッドで実行されるデーモンタイマーを使用して、サービスをクラッシュさせて正常にテストしました) – Hugo

2

/発見にNsdサービスを停止します。私はこれがあなたがすることだと思うので、あなたの "アプローチ"は正しいです。

問題については、Android Nsdにご連絡ください。 Android 6.0の時点でまだ開発者が他のフレームワークを使用するように修正されていないというフレームワークを持つbugsがたくさんあります(その中に問題が見つかります)。

バックの問題に取得、あなたは、UncaughtExceptionHandlerを試すだけですべてのコールバックが非同期システムによって呼び出されることに注意してください、そしてそれは」、あなたが言ったように、ので、それは、mRegistrationListener.onServiceUnregistered()を呼び出したとき、あなたはNPEを取得することがありますもはや「」の周りにはありません。いくつかのメソッドのサービスクリーンアップとして

、理論的には可能であるが、唯一のNsdManagerソースコードのカスタマイズ後(アクセス修飾子が到達し、それを削除するにつながる別のプロセスからmRegistrationListenerの登録を解除するために変更する必要がありますリスナーマップNsdManagerから)。しかし、アプリが市場に公開されるのであれば意味をなさない。

もう一度試してみてはいかがですか?私が正しく覚えていれば(間違いかもしれません)、Nsdを無効にすると必要なクリーンアップが行われます。私はadbを経由して、それを試してみました:

// Disable 
adb shell service call servicediscovery 2 
// Enable 
adb shell service call servicediscovery 2 i32 1 

しかし、プログラムでこれらの呼び出しを行うことは些細なことと、最も可能性の高い、もう一度、あなたのアプリの聴衆を制限ルートを必要としないかもしれないことに、注意してください。

@thrilによって提案されたkillBackgroundProcesses()メソッドに関しては、パラメータとしてappのパッケージ名を持つ文字列を受け取ります。しかしservicediscoveryはアプリではなく、システムサービスです。また、実行時にプロセスを強制終了することはできますが(私にはわからないが)注意が必要です。システムにどのような影響があるのか​​を調査し、必要に応じてサービスが再開されるようにする必要がありますシステムまたは手動で)。ここでもまた、このルートを実行する必要があります。

答えを要約すると、Nsdを続行する前に、時間と労力を無駄にしないように、機能/バグに関する検索を行うことを強くお勧めします。上方に設けられたリンクに加えて、いくつかの参照:

  1. NSD Device Lost Message Not Received on Disabling Wifi
  2. NsdManager doesn't stop service discovery

P.S.個人的に私は複数のNsdフレームワークのバグに苦しんで、自分のフレームワークを作成しました。

+0

ありがとう@Onik、デーモンタイマー( 'Timer timer = new Timer(true); timer.schedule(new SimulateUncaughtException()、2000);を使用して、別のスレッドからメインサービスをクラッシュさせることによって正常にテストされた' UncaughtExceptionHandler ' ) – Hugo

+0

非常によく@Hugo、別のスレッドで 'Nsd'作業を処理することは良いアイデアです - 明らかに、その場合にサービスを登録解除する時間があります。しかし、特に 'Wifi'(' Ethernet')をオン/オフするときに 'Nsd'コールバックをすべてチェックすることをお勧めします... – Onik