*この問題は、アクティビティ クラスで使用したメソッド "onDestroy()" に関連している可能性があります。助けてください *
BluetoothHDPActivity.java
パッケージ com.example.bluetoothhdp;
public class BluetoothHDPActivity extends Activity
{
private static final String TAG = "BluetoothHealthActivity";
private static final int HEALTH_PROFILE_SOURCE_DATA_TYPE = 0x1007;
private static final int REQUEST_ENABLE_BT = 1;
private TextView mConnectIndicator;
private ImageView mDataIndicator;
private TextView mStatusMessage;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice[] mAllBondedDevices;
private BluetoothDevice mDevice;
private int mDeviceIndex = 0;
private Resources mRes;
private Messenger mHealthService;
private boolean mHealthServiceBound;
private Handler mIncomingHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case BluetoothHDPService.STATUS_HEALTH_APP_REG:mStatusMessage.setText(
String.format(mRes.getString(R.string.cancel),
msg.arg1));
break;
case BluetoothHDPService.STATUS_HEALTH_APP_UNREG:
mStatusMessage.setText(
String.format(mRes.getString(R.string.copy),
msg.arg1));
break;
case BluetoothHDPService.STATUS_READ_DATA:
mStatusMessage.setText(mRes.getString(R.string.copyUrl));
mDataIndicator.setImageLevel(1);
break;
case BluetoothHDPService.STATUS_READ_DATA_DONE:
mStatusMessage.setText(mRes.getString(R.string.cut));
mDataIndicator.setImageLevel(0);
break;
case BluetoothHDPService.STATUS_CREATE_CHANNEL:
mStatusMessage.setText(
String.format(mRes.getString(R.string.defaultMsisdnAlphaTag),
msg.arg1));
mConnectIndicator.setText("connected");
break;
case BluetoothHDPService.STATUS_DESTROY_CHANNEL:
mStatusMessage.setText(
String.format(mRes.getString(R.string.defaultVoiceMailAlphaTag),
msg.arg1));
mConnectIndicator.setText("Disconnected");
break;
default:
super.handleMessage(msg);
}
}
};
private final Messenger mMessenger = new Messenger(mIncomingHandler);
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null)
{
Toast toast= Toast.makeText(this,"Bluetooth is not available", Toast.LENGTH_LONG);
toast.show();
finish();
return;
}
setContentView(R.layout.activity_list_item);
mConnectIndicator = (TextView) findViewById(R.id.addToDictionary);
mStatusMessage = (TextView) findViewById(R.id.background);
mRes = getResources();
mHealthServiceBound = false;
Button registerAppButton = (Button) findViewById(R.id.button1);
registerAppButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
sendMessage(BluetoothHDPService.MSG_REG_HEALTH_APP,
HEALTH_PROFILE_SOURCE_DATA_TYPE);
}
});
Button unregisterAppButton = (Button) findViewById(R.id.button2);
unregisterAppButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
sendMessage(BluetoothHDPService.MSG_UNREG_HEALTH_APP, 0);
}
});
Button connectButton = (Button) findViewById(R.id.button3);
connectButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
mAllBondedDevices =
(BluetoothDevice[]) mBluetoothAdapter.getBondedDevices().toArray(
new BluetoothDevice[0]);
if (mAllBondedDevices.length > 0)
{
int deviceCount = mAllBondedDevices.length;
if (mDeviceIndex < deviceCount) mDevice = mAllBondedDevices[mDeviceIndex];
else
{
mDeviceIndex = 0;
mDevice = mAllBondedDevices[0];
}
String[] deviceNames = new String[deviceCount];
int i = 0;
for (BluetoothDevice device : mAllBondedDevices)
{
deviceNames[i++] = device.getName();
}
SelectDeviceDialogFragment deviceDialog =
SelectDeviceDialogFragment.newInstance(deviceNames, mDeviceIndex);
deviceDialog.show(getFragmentManager(), "deviceDialog");
}
}
});
Button disconnectButton = (Button) findViewById(R.id.closeButton);
disconnectButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
disconnectChannel();
}
});
registerReceiver(mReceiver, initIntentFilter());
}
private ServiceConnection mConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName name, IBinder service)
{
mHealthServiceBound = true;
Message msg = Message.obtain(null, BluetoothHDPService.MSG_REG_CLIENT);
msg.replyTo = mMessenger;
mHealthService = new Messenger(service);
try {
mHealthService.send(msg);
} catch (RemoteException e)
{
Log.w(TAG, "Unable to register client to service.");
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name)
{
mHealthService = null;
mHealthServiceBound = false;
}
};
@Override
protected void onDestroy()
{
super.onDestroy();
if (mHealthServiceBound) unbindService(mConnection);
unregisterReceiver(mReceiver);
}
@Override
protected void onStart()
{
super.onStart();
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
} else
{
initialize();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch (requestCode)
{
case REQUEST_ENABLE_BT:
if (resultCode == Activity.RESULT_OK)
{
initialize();
} else {
finish();
return;
}
}
}
public void setDevice(int position)
{
mDevice = this.mAllBondedDevices[position];
mDeviceIndex = position;
}
private void connectChannel()
{
sendMessageWithDevice(BluetoothHDPService.MSG_CONNECT_CHANNEL);
}
private void disconnectChannel()
{
sendMessageWithDevice(BluetoothHDPService.MSG_DISCONNECT_CHANNEL);
}
private void initialize()
{
Intent intent = new Intent(this, BluetoothHDPService.class);
startService(intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
private IntentFilter initIntentFilter()
{
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
return filter;
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action))
{
if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) ==
BluetoothAdapter.STATE_ON)
{
initialize();
}
}
}
};
private void sendMessage(int what, int value)
{
if (mHealthService == null) {
Log.d(TAG, "Health Service not connected.");
return;
}
try {
mHealthService.send(Message.obtain(null, what, value, 0));
} catch (RemoteException e)
{
Log.w(TAG, "Unable to reach service.");
e.printStackTrace();
}
}
private void sendMessageWithDevice(int what)
{
if (mHealthService == null)
{
Log.d(TAG, "Health Service not connected.");
return;
}
try {
mHealthService.send(Message.obtain(null, what, mDevice));
} catch (RemoteException e)
{
Log.w(TAG, "Unable to reach service.");
e.printStackTrace();
}
}
public static class SelectDeviceDialogFragment extends DialogFragment
{
public static SelectDeviceDialogFragment newInstance(String[] names, int position)
{
SelectDeviceDialogFragment frag = new SelectDeviceDialogFragment();
Bundle args = new Bundle();
args.putStringArray("names", names);
args.putInt("position", position);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
String[] deviceNames = getArguments().getStringArray("names");
int position = getArguments().getInt("position", -1);
if (position == -1) position = 0;
return new AlertDialog.Builder(getActivity())
.setTitle("select device")
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
((BluetoothHDPActivity) getActivity()).connectChannel();
}
})
.setSingleChoiceItems(deviceNames, position,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
((BluetoothHDPActivity) getActivity()).setDevice(which);
}
}
)
.create();
}
}}
BluetoothHDPService.java
パッケージ com.example.bluetoothhdp;
public class BluetoothHDPService extends Service
{
private static final String TAG = "BluetoothHDPService";
public static final int RESULT_OK = 0;
public static final int RESULT_FAIL = -1;
public static final int STATUS_HEALTH_APP_REG = 100;
public static final int STATUS_HEALTH_APP_UNREG = 101;
public static final int STATUS_CREATE_CHANNEL = 102;
public static final int STATUS_DESTROY_CHANNEL = 103;
public static final int STATUS_READ_DATA = 104;
public static final int STATUS_READ_DATA_DONE = 105;
public static final int MSG_REG_CLIENT = 200;
public static final int MSG_UNREG_CLIENT = 201;
public static final int MSG_REG_HEALTH_APP = 300;
public static final int MSG_UNREG_HEALTH_APP = 301;
public static final int MSG_CONNECT_CHANNEL = 400;
public static final int MSG_DISCONNECT_CHANNEL = 401;
private BluetoothHealthAppConfiguration mHealthAppConfig;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothHealth mBluetoothHealth;
private BluetoothDevice mDevice;
private int mChannelId;
private Messenger mClient;
private class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case MSG_REG_CLIENT:
Log.d(TAG, "Activity client registered");
mClient = msg.replyTo;
break;
case MSG_UNREG_CLIENT:
mClient = null;
break;
case MSG_REG_HEALTH_APP:
registerApp(msg.arg1);
break;
case MSG_UNREG_HEALTH_APP:
unregisterApp();
break;
case MSG_CONNECT_CHANNEL:
mDevice = (BluetoothDevice) msg.obj;
connectChannel();
break;
case MSG_DISCONNECT_CHANNEL:
mDevice = (BluetoothDevice) msg.obj;
disconnectChannel();
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public void onCreate()
{
super.onCreate();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())
{
stopSelf();
return;
}
if (!mBluetoothAdapter.getProfileProxy(this, mBluetoothServiceListener,
BluetoothProfile.HEALTH)) {
Toast toast= Toast.makeText(this, "HDP is not available",Toast.LENGTH_LONG);
toast.show();
stopSelf();
return;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "BluetoothHDPService is running.");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent)
{
return mMessenger.getBinder();
};
private void registerApp(int dataType)
{
mBluetoothHealth.registerSinkAppConfiguration(TAG, dataType, mHealthCallback);
}
private void unregisterApp()
{
mBluetoothHealth.unregisterAppConfiguration(mHealthAppConfig);
}
private void connectChannel()
{
Log.i(TAG, "connectChannel()");
mBluetoothHealth.connectChannelToSource(mDevice, mHealthAppConfig);
}
private void disconnectChannel()
{
Log.i(TAG, "disconnectChannel()");
mBluetoothHealth.disconnectChannel(mDevice, mHealthAppConfig, mChannelId);
}
private final BluetoothProfile.ServiceListener mBluetoothServiceListener =
new BluetoothProfile.ServiceListener()
{
public void onServiceConnected(int profile, BluetoothProfile proxy)
{
if (profile == BluetoothProfile.HEALTH)
{
mBluetoothHealth = (BluetoothHealth) proxy;
if (Log.isLoggable(TAG, Log.DEBUG))
Log.d(TAG, "onServiceConnected to profile: " + profile);
}
}
public void onServiceDisconnected(int profile)
{
if (profile == BluetoothProfile.HEALTH)
{
mBluetoothHealth = null;
}
}
};
private final BluetoothHealthCallback mHealthCallback = new BluetoothHealthCallback()
{
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,int status)
{
if (status == BluetoothHealth.APP_CONFIG_REGISTRATION_FAILURE)
{
mHealthAppConfig = null;
sendMessage(STATUS_HEALTH_APP_REG, RESULT_FAIL);
} else if (status == BluetoothHealth.APP_CONFIG_REGISTRATION_SUCCESS)
{
mHealthAppConfig = config;
sendMessage(STATUS_HEALTH_APP_REG, RESULT_OK);
} else if (status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE ||
status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS)
{
sendMessage(STATUS_HEALTH_APP_UNREG,
status == BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS ?
RESULT_OK : RESULT_FAIL);
}
}
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd,
int channelId)
{
if (Log.isLoggable(TAG, Log.DEBUG))
Log.d(TAG, String.format("prevState\t%d ----------> newState\t%d",
prevState, newState));
if (prevState == BluetoothHealth.STATE_CHANNEL_DISCONNECTED &&
newState == BluetoothHealth.STATE_CHANNEL_CONNECTED)
{
if (config.equals(mHealthAppConfig))
{
mChannelId = channelId;
sendMessage(STATUS_CREATE_CHANNEL, RESULT_OK);
(new ReadThread(fd)).start();
} else
{
sendMessage(STATUS_CREATE_CHANNEL, RESULT_FAIL);
}
} else if (prevState == BluetoothHealth.STATE_CHANNEL_CONNECTING &&
newState == BluetoothHealth.STATE_CHANNEL_DISCONNECTED)
{
sendMessage(STATUS_CREATE_CHANNEL, RESULT_FAIL);
} else if (newState == BluetoothHealth.STATE_CHANNEL_DISCONNECTED)
{
if (config.equals(mHealthAppConfig))
{
sendMessage(STATUS_DESTROY_CHANNEL, RESULT_OK);
} else
{
sendMessage(STATUS_DESTROY_CHANNEL, RESULT_FAIL);
}
}
}
};
private void sendMessage(int what, int value)
{
if (mClient == null)
{
Log.d(TAG, "No clients registered.");
return;
}
try
{
mClient.send(Message.obtain(null, what, value, 0));
} catch (RemoteException e)
{
e.printStackTrace();
}
}
private class ReadThread extends Thread
{
private ParcelFileDescriptor mFd;
public ReadThread(ParcelFileDescriptor fd)
{
super();
mFd = fd;
}
@Override
public void run()
{
FileInputStream fis = new FileInputStream(mFd.getFileDescriptor());
final byte data[] = new byte[8192];
try {
while(fis.read(data) > -1)
{
sendMessage(STATUS_READ_DATA, 0);
}
} catch(IOException ioe) {}
if (mFd != null)
{
try {
mFd.close();
} catch (IOException e) { /* Do nothing. */ }
}
sendMessage(STATUS_READ_DATA_DONE, 0);
}
}}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluetooth.health"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
<uses-permission
android:name="android.permission.BLUETOOTH" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"/>
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name="com.example.bluetoothhdp.BluetoothHDPActivity"
android:label="@string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".BluetoothHDPService" />
</application>
</manifest>
LogCat
08-26 16:37:44.773: E/AndroidRuntime(802): FATAL EXCEPTION: main
08-26 16:37:44.773: E/AndroidRuntime(802): java.lang.RuntimeException: Unable to destroy activity {com.example.bluetoothhdp/com.example.bluetoothhdp.BluetoothHDPActivity}: java.lang.IllegalArgumentException: Receiver not registered: com.example.bluetoothhdp.BluetoothHDPActivity$3@40ce3da8
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3451)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3469)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ActivityThread.access$1200(ActivityThread.java:141)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1287)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.os.Handler.dispatchMessage(Handler.java:99)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.os.Looper.loop(Looper.java:137)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ActivityThread.main(ActivityThread.java:5041)
08-26 16:37:44.773: E/AndroidRuntime(802): at java.lang.reflect.Method.invokeNative(Native Method)
08-26 16:37:44.773: E/AndroidRuntime(802): at java.lang.reflect.Method.invoke(Method.java:511)
08-26 16:37:44.773: E/AndroidRuntime(802): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
08-26 16:37:44.773: E/AndroidRuntime(802): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
08-26 16:37:44.773: E/AndroidRuntime(802): at dalvik.system.NativeStart.main(Native Method)
08-26 16:37:44.773: E/AndroidRuntime(802): Caused by: java.lang.IllegalArgumentException: Receiver not registered: com.example.bluetoothhdp.BluetoothHDPActivity$3@40ce3da8
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:657)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1339)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:445)
08-26 16:37:44.773: E/AndroidRuntime(802): at com.example.bluetoothhdp.BluetoothHDPActivity.onDestroy(BluetoothHDPActivity.java:254)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.Activity.performDestroy(Activity.java:5273)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1110)
08-26 16:37:44.773: E/AndroidRuntime(802): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3438)
08-26 16:37:44.773: E/AndroidRuntime(802): ... 11 more