我试图开发一个应用程序,该应用程序将检测BLE模块并在选择模块时连接到GATT服务。我可以发现BLE模块并选择它以连接到GATT服务。但是状态一旦从“连接”变为“已连接”,应用就会崩溃。
我一直在寻找可用的在线解决方案。查阅了我的参考教程。
这是我的主要活动:
//Error from logcat next line
public class MainActivity extends Activity implements ActionBar.TabListener, ServicesFragment.IServiceFragmentInteraction,
AdapterView.OnItemSelectedListener{
private static final String TAG = MainActivity.class.getSimpleName();
public void onServiceConnected() {
if (!mBluetoothLeService.initialize(this)) {
finish();
}
}
public final MyBroadcastReceiver mGattUpdateReceiver = new MyBroadcastReceiver();
private List<BluetoothGattService> mServices;
private void sendToActiveFragment(List<BluetoothGattService> services) {
mServices = services;
Fragment fragment = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
if (fragment == null) {
return;
}
if (ServicesFragment.class.isInstance(fragment)) {
ServicesFragment servicesFragment = (ServicesFragment) fragment;
servicesFragment.displayGattServices(services);//Error from logcat
}
}
private void sendToActiveFragment(boolean connected) {
Fragment fragment = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
if (fragment == null) {
return;
}
}
private void sendToActiveFragment(final BluetoothGattCharacteristic characteristic) {
Fragment fragment = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
if (fragment == null) {
return;
}
}
private void sendToActiveFragment(int rssi) {
Fragment fragment = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
if (fragment == null) {
return;
}
}
private void sendToActiveFragment(UUID uuid, int type, byte[] data) {
Fragment fragment = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
if (fragment == null) {
return;
}
if (ServicesFragment.class.isInstance(fragment)) {
runOnUiThread(() -> {
View v = fragment.getView();
Log.i("SERVICE", "gotData, uuid: " + uuid);
Log.i("SERVICE", "wanted __UUID: " + ((ServicesFragment) fragment).currentUuid);
if (((ServicesFragment) fragment).currentUuid.equals(uuid.toString())) {
StringBuilder stringBuilder = new StringBuilder(data.length);
for (byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
TextView tvValue = v.findViewById(R.id.tvValue);
tvValue.setText(new String(data) + "\n<" + stringBuilder.toString() + ">");
Log.i("SERVICE", "gotData: " + tvValue.getText().toString());
}
});
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle("");
getActionBar().setLogo(R.drawable.v_daq_logo);
getActionBar().setDisplayUseLogoEnabled(true);
setContentView(R.layout.activity_main);
mViewPager = findViewById(R.id.pager);
tvStatus = findViewById(R.id.tvStatus);
rlProgress = findViewById(R.id.rlProgress);
final Intent intent = getIntent();
isRemoteMode = intent.hasExtra(EXTRA_REMOTE);
updateStatus();
if(isRemoteMode) {
mViewPager.setVisibility(View.GONE);
rlProgress.setVisibility(View.GONE);
FragmentManager fragmentManager = new FragmentActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
// remoteControlFragment = new RemoteControlFragment();
// transaction.add(R.id.llMain, remoteControlFragment);
transaction.commit();
} else {
connectToDevice(intent.getParcelableExtra(EXTRA_DEVICE));
final ActionBar actionBar = getActionBar();
setTabsWithPagerAdapter(actionBar);
final String name = mDevice.getName();
if (!TextUtils.isEmpty(name)) {
getActionBar().setTitle(name);
} else {
getActionBar().setTitle(mDevice.getAddress());
}
actionBar.setDisplayShowCustomEnabled(true);
}
}
private void connectToDevice(BluetoothDeviceRepresentation bluetoothDevice) {
mDevice = bluetoothDevice;
mBluetoothLeService = new BluetoothLeService();
onServiceConnected();
}
private void setTabsWithPagerAdapter(final ActionBar actionBar) {
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mSectionsPagerAdapter = new SectionsPagerAdapter(new FragmentActivity().getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
updateStatus();
switch (position) {
case 1:
ServicesFragment mServicesFragment = (ServicesFragment) mSectionsPagerAdapter.getItem(position);
if (!mServicesFragment.hasGottenServices()) {
if (mServices != null)
mServicesFragment.displayGattServices(mServices);
}
break;
default:
break;
}
}
});
mViewPager.setOffscreenPageLimit(3);
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
public boolean isConnected() {
return mConnectionState == ConnectionState.CONNECTED;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_connected, menu);
if(!isRemoteMode) {
switch (mConnectionState) {
case CONNECTED:
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
break;
case CONNECTING:
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(false);
break;
case DISCONNECTED:
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
break;
}
} else {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_connect:
mBluetoothLeService.connect(mDevice);
mConnectionState = ConnectionState.CONNECTING;
invalidateOptionsMenu();
updateStatus();
rlProgress.setVisibility(View.VISIBLE);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
updateStatus();
rlProgress.setVisibility(View.VISIBLE);
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
Fragment fragment = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
if(fragment instanceof ServicesFragment &&
((ServicesFragment) fragment).isCharacteristicViewVisible()) {
((ServicesFragment) fragment).backButtonPressed();
} else {
super.onBackPressed();
}
}
@Override
public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) {
}
@Override
public void onRead(BluetoothGattCharacteristic characteristic) {
try {
mBluetoothLeService.readCharacteristic(characteristic);
} catch (Exception ignore) {
ignore.printStackTrace();
}
}
@Override
public void onWrite(BluetoothGattCharacteristic characteristic, byte[] value) {
try {
mBluetoothLeService.writeCharacteristic(characteristic, value);
} catch (Exception ignore) {
ignore.printStackTrace();
}
}
@Override
public void onNotify(BluetoothGattCharacteristic characteristic, boolean enabled) {
try {
mBluetoothLeService.setCharacteristicNotification(characteristic, enabled);
} catch (Exception ignore) {
ignore.printStackTrace();
}
}
// @Override
// public void onSendMessage(BluetoothGattCharacteristic characteristic, byte[] message) {
// try {
// mBluetoothLeService.writeCharacteristic(characteristic, message);
// } catch (Exception ignore) {}
// }
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
try {
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
} catch (Exception ignore) {}
try {
mBluetoothLeService.connect(mDevice);
mConnectionState = ConnectionState.CONNECTING;
invalidateOptionsMenu();
updateStatus();
rlProgress.setVisibility(View.VISIBLE);
} catch (Exception ignore) {}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
public BluetoothLeService getLeService() {
return mBluetoothLeService;
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
private ServicesFragment mServicesFragment = null;
@Override
public Fragment getItem(int position) {
if (position == 0) {
if (mServicesFragment == null) {
mServicesFragment = ServicesFragment.newInstance();
}
return mServicesFragment;
}
// } else if (position == 1) {
// if (mChatFragment == null) {
// mChatFragment = ChatFragment.newInstance();
// }
// return mChatFragment;
// }
// else {
// return mServicesFragment;
// }
return null;
}
@Override
public int getCount() {
return 0;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
}
return null;
}
}
private class MyBroadcastReceiver implements BluetoothLeServiceReceiver {
@Override
public void onDescriptorWrite() {
// TODO check other solution
}
@Override
public void onRssiUpdate(int rssi) {
runOnUiThread(() -> sendToActiveFragment(rssi));
}
@Override
public void onDataAvailable(UUID uUid, int type, byte[] data) {
sendToActiveFragment(uUid, type, data);
}
@Override
public void onServicesDiscovered() {
runOnUiThread(() -> {
sendToActiveFragment(mBluetoothLeService.getSupportedGattServices());//error from logcat
updateStatus();
for (BluetoothGattService service : mBluetoothLeService.getSupportedGattServices()) {
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
String uuid = characteristic.getUuid().toString();
}
}
});
}
@Override
public void onGattDisconnected() {
runOnUiThread(() -> {
mConnectionState = ConnectionState.DISCONNECTED;
invalidateOptionsMenu();
sendToActiveFragment(false);
updateStatus();
rlProgress.setVisibility(View.GONE);
});
}
@Override
public void onGattConnected() {
runOnUiThread(() -> {
mConnectionState = ConnectionState.CONNECTED;
// invalidateOptionsMenu();
updateStatus();
sendToActiveFragment(true);
rlProgress.setVisibility(View.GONE);
});
}
}
}
这是我的服务片段:
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
List<BluetoothGattService> mServices = new ArrayList<>();
public void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null) return;
mServices = gattServices;
String uuid = null;
// Error is next line. from logcat ServicesFragment.java:92
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, GattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, GattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
}
这是Logcat:
2019-09-25 11:04:58.822 7494-7494/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2019-09-25 11:04:58.823 7494-7494/? E/Zygote: accessInfo : 1
2019-09-25 11:05:08.637 7494-7494/com.example.v_daq20 D/AndroidRuntime: Shutting down VM
2019-09-25 11:05:08.639 7494-7494/com.example.v_daq20 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.v_daq20, PID: 7494
java.lang.IllegalStateException: Fragment ServicesFragment{c5195ea} not attached to a context.
at androidx.fragment.app.Fragment.requireContext(Fragment.java:696)
at androidx.fragment.app.Fragment.getResources(Fragment.java:760)
at com.example.v_daq20.ServicesFragment.displayGattServices(ServicesFragment.java:92)
at com.example.v_daq20.MainActivity.sendToActiveFragment(MainActivity.java:81)
at com.example.v_daq20.MainActivity.access$900(MainActivity.java:39)
at com.example.v_daq20.MainActivity$MyBroadcastReceiver.lambda$onServicesDiscovered$1$MainActivity$MyBroadcastReceiver(MainActivity.java:501)
at com.example.v_daq20.-$$Lambda$MainActivity$MyBroadcastReceiver$MsdzV47oUkUeA45nRVbtDGzhQJE.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7037)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
2019-09-25 11:05:08.695 7494-7508/com.example.v_daq20 D/BluetoothGatt: onConnectionUpdated() - Device=D4:CA:6E:F0:B7:ED interval=39 latency=0 timeout=500 status=0
2019-09-25 11:05:13.672 7494-7508/com.example.v_daq20 D/BluetoothGatt: onConnectionUpdated() - Device=D4:CA:6E:F0:B7:ED interval=39 latency=0 timeout=200 status=0
在进行Android应用开发时,我是一个完全的新手。因此解决方案的详细答案将不胜感激。谢谢!