Приложение продолжает падать, когда подключен сервис GATT - PullRequest
0 голосов
/ 25 сентября 2019

Я пытался разработать приложение, которое будет определять модуль 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.поэтому подробный ответ с решением будет высоко ценится.спасибо !!

...