問題は簡単です。Android では、ライブラリ関数を呼び出す必要があるメソッドがあります。この呼び出しは、処理する必要があるコールバックを通知します。メソッドから戻る前に、そのコールバックが通知されるのを待つ必要があります。
モニター オブジェクトの wait() メソッドと notify() メソッドがうまくいくと思いました。そうではありません。
Connection
基本的に、呼び出し元のメソッドでインスタンス化する監視オブジェクトが呼び出されます。次に、このメソッドは、Android ライブラリ メソッドを呼び出してオブジェクトを「登録解除」するループを実行します。残念ながら、このメソッドへの応答は何らかのコールバックで提供されます。そのため、このメソッドを使用しConnection.wait(10000)
てコールバックを待機し、コールバックでは、connection.notify()
完了したときに通知するために使用します (もちろん、すべて同期されています)。ただし、connection.notify()
は をリリースしませんconnection.wait(10000)
。Android logcat から、登録解除が成功したことがわかりますが、次の登録解除タスクが試行されるまで、常に 10 秒待たなければなりません。
呼び出しメソッドとコールバックのコードは次のとおりです。これが失敗するという私の推論で、私はなんてばかげた仮定をしていますか。私が見る限り、呼び出し元のメソッド (スレッド) は確実に監視オブジェクトを所有し、connection.wait(10000)
!のコールバックにそれを渡します。
たぶん、この問題に対して完全に間違ったアプローチを使用していますか? (私が欲しいのは、すべての登録解除が完了するまで発信者をブロックする方法です。)
public void clearRegistrations()
{
connection = new Connection();
// Tell the callback to notify() when a result is obtained
connection.setUseNotify(true);
for(BluetoothHealthAppConfiguration btConfig : btHealthAppConfigs)
{
// Initialize Connection object to not connected
connection.setConnectionState(false);
if(btHealth.unregisterAppConfiguration(btConfig))
{
try
{
synchronized (connection)
{
connection.wait(10000);
// See if we were signaled or timed out
if(!connection.getConnectionState())
{
Log.i(TAG, "Unregistration attempt timed out or failed; trying next un-registration");
}
}
}
// This should not happen
catch(InterruptedException ie)
{
Log.i(TAG, "The InterrupedException is signaled.");
}
// This should not happen.
catch(IllegalMonitorStateException ime)
{
Log.i(TAG, "wait() method threw an IllegalMonitorStateException. Message: " + ime.getMessage());
}
}
else
{
Toast.makeText(context, "Un-Registration API returned failure", Toast.LENGTH_SHORT).show();
}
}
btHealthAppConfigs.clear();
connection.setConnectionState(false);
connection.setUseNotify(false);
}
コールバックは次のとおりで、上記のメソッドと同じクラスですが、Android で非常に人気のある「onSomeEvent()」の 1 つです。
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration btAppConfig, int status)
{
if (status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE)
{
Log.i(TAG, "Un-Registration of the Bluetooth Health Application failed");
if(connection.useNotify() == true)
{
synchronized (connection)
{
Log.i(TAG, "Signal unregistration failure");
// just indicate signaled
connection.setConnectionState(true);
connection.notify();
}
}
}
else if(status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS)
{
Log.i(TAG, "Un-Registration of the Bluetooth Health Application successful");
if(connection.useNotify() == true)
{
synchronized (connection)
{
Log.i(TAG, "Signal unregistration success");
connection.setConnectionState(true);
connection.notify();
}
}
}
}