java - 蓝牙回调函数 onCharacteristicRead 没有对使用 <API 21 的另一个 Activity 进行 Intent 调用。不在 Marshmallow 中

标签 java android android-intent bluetooth

我正在尝试从低功耗蓝牙回调函数 onCharacteristicRead() 进行 Intent 调用。请告诉我哪里错了。

我不确定它是否与我们为 Intent 类提供的上下文或其他东西有关。

它向我显示以下错误:

"Unable to start activity ComponentInfo::java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference"

下面是代码示例:

package com.example.pushkara.msable;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
import android.content.Context;

import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.ConsoleHandler;

@TargetApi(18)
public class MainActivity extends AppCompatActivity {

    private BluetoothAdapter mBluetoothAdapter;
    private int REQUEST_ENABLE_BT = 1;
    private Handler mHandler;
    private static final long SCAN_PERIOD = 5000;
    private BluetoothLeScanner mLEScanner;
    private ScanSettings settings;
    private List<ScanFilter> filters;
    private BluetoothGatt mGatt;
    private  MsaScanCallback mScanCallback;
    private Button mCheckInButton;
    private Button mCheckOutButton;
    private Button mNewButton;
    private Boolean buttonvalue = false;

    public static TextView mSecurityCode;
    public static TextView rssiNdistance;


    public final static UUID UUID_MSA_APP =  UUID.fromString("13333333-3333-3333-3333-333333333337");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mCheckInButton = (Button)findViewById(R.id.checkIn);
        mCheckOutButton = (Button)findViewById(R.id.checkOut);

        mSecurityCode= (TextView)findViewById(R.id.securityCode);
        rssiNdistance= (TextView)findViewById(R.id.rssiNdistance);
        mCheckOutButton.setOnClickListener(new MsaCheckInCheckout(false));
        mCheckInButton.setOnClickListener(new MsaCheckInCheckout(true));
        try {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


                if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("This app needs location access");
                    builder.setMessage("Please grant location access so this app can detect msa server.");
                    builder.setPositiveButton(android.R.string.ok, null);
                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @TargetApi(Build.VERSION_CODES.M)
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
                        }
                    });
                    builder.show();
                }

            }

            mHandler = new Handler();

            if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                Toast.makeText(this, "BLE Not Supported",
                        Toast.LENGTH_SHORT).show();
                finish();
            }

            final BluetoothManager bluetoothManager =
                    (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();


        }
        catch(Exception ex){
            Log.i("msable"," [@@MA]::::Exception 1" +ex.toString());
            mSecurityCode.setText("[@@MA]Exc1" + ex.toString());
        }
    }



    private final ConnectDevice connectToDeviceCallback = new ConnectDevice() {

        @Override
        public void OnConnectToDevice(BluetoothDevice device){
               connectToDevice(device);
        }
    };


    public class MsaCheckInCheckout implements View.OnClickListener {
        private boolean mCheckIn;
        public MsaCheckInCheckout(boolean isCheckIn){
            mCheckIn =isCheckIn;
        }
        @Override
        public void onClick (View v) {
            try {
                // your code here;
                Log.i("CLICK", mCheckIn + "");

                if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
                    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                } else {
                    if (Build.VERSION.SDK_INT >= 21) {

                        if (mGatt != null) {
                            mGatt.close();
                            mGatt = null;
                        }


                        mScanCallback = new MsaScanCallback(connectToDeviceCallback);
                        mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                        settings = new ScanSettings.Builder()
                                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                                .build();


                        ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUID_MSA_APP)).build();

                        filters = new ArrayList<>();

                        filters.add(filter);
                    }
                    scanLeDevice(true);
                }
            }
            catch(Exception ex){
                Log.i("msable","[@@MA] ::::Exception  2" +ex.toString());
                mSecurityCode.setText("[@@MA]Ex2" + ex.toString());
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
        try {
            switch (requestCode) {
                case 1: {
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Log.d("1", "coarse location permission granted");
                    } else {
                        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle("Functionality limited");
                        builder.setMessage("Since location access has not been granted, this app will not be able to discover msa server");
                        builder.setPositiveButton(android.R.string.ok, null);
                        builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                            @Override

                            public void onDismiss(DialogInterface dialog) {
                            }

                        });
                        builder.show();
                    }
                }
            }
        }
        catch(Exception ex){
            Log.i("msable","[@@MA] ::::Exception  3" +ex.toString());
            mSecurityCode.setText("[@@MA]Ex3" + ex.toString());
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
            scanLeDevice(false);
        }
    }

    @Override
    protected void onDestroy() {

        super.onDestroy();

        if (mGatt == null) {
            return;
        }
        mGatt.close();
        mGatt = null;

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        try {
            if (requestCode == REQUEST_ENABLE_BT) {
                if (resultCode == Activity.RESULT_CANCELED) {
                    //Bluetooth not enabled.
                    finish();
                    return;
                }
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
        catch(Exception ex){
            Log.i("msable","[@@MA] ::::Exception  4" +ex.toString());
            mSecurityCode.setText("[@@MA]Ex4" + ex.toString());
        }
    }
    private void scanLeDevice(final boolean enable) {

        try {
            Log.i("BLE", "**** scanLeDevice");

            if(mBluetoothAdapter != null || mLEScanner !=null) {

                Log.i("BLE", "**** Object not null proceed to stop scan");
                if (enable) {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {

                            if (Build.VERSION.SDK_INT < 21) {
                                mBluetoothAdapter.stopLeScan(mLeScanCallback);

                                Log.i("BLE", "mBluetoothAdapter STOP SCAN");
                            } else {

                                Log.i("BLE", "mLEScanner STOP SCAN");
                                if(mLEScanner !=null) {
                                    Log.i("BLE", "mLEScanner not null proceed for stop ");
                                }
                                else
                                {
                                    Log.i("BLE", "mLEScanner is null !!!!!");
                                }
                                mLEScanner.stopScan(mScanCallback);


                            }
                        }
                    }, SCAN_PERIOD);
                    if (Build.VERSION.SDK_INT < 21) {

                        mBluetoothAdapter.startLeScan(mLeScanCallback);
                        Log.i("BLE", "mBluetoothAdapter START SCAN");
                    } else {
                        Log.i("START SCAN", "START SCAN");

                        mLEScanner.startScan(filters, settings, mScanCallback);

                    }
                } else {
                    if (Build.VERSION.SDK_INT < 21) {
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);

                    } else {
                        mLEScanner.stopScan(mScanCallback);

                    }
                }
            }
            else
            {
                Log.i("BLE","**** Object is null");

            }
        }
        catch(Exception ex){
            Log.i("msable","[@@MA] ::::Exception  5" +ex.toString());
            mSecurityCode.setText("[@@MA]Ex5" + ex.toString());
        }
    }

    double getDistance(int rssi) {
         return Math.pow(10d, ((double)  -52 - rssi) / (10 * 2));
    }


    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {

                @Override
                public void onLeScan(final BluetoothDevice device, final int rssi,
                                     byte[] scanRecord) {
                    try {
                            Log.i("BLE","**** onLeScan LeScanCallback");

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Log.i("onLeScan", device.toString());

                                double distance = getDistance(rssi);
                                rssiNdistance.setText("rssi:"+rssi+" distance:"+distance);

                                if (distance <= 1) {

                                    connectToDevice(device);
                                }
                                else{
                                    mSecurityCode.setText("Out of Range!!!");
                                }


                            }
                        });
                    }
                    catch(Exception ex){
                        Log.i("msable","[@@MA] ::::Exception  6" +ex.toString());
                        mSecurityCode.setText("[@@MA]Ex6" + ex.toString());
                    }
                }
            };

    public void connectToDevice(BluetoothDevice device) {
        Log.i("BLE","**** connectToDevice");
        if (mGatt == null) {
            mGatt = device.connectGatt(this, false, gattCallback);
            scanLeDevice(false);// will stop after first device detection

        }else{
            Log.i("gatt status","ATT");
        }

    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            try {
                Log.i("BLE","**** gattCallback onConnectionStateChange Status: "+status);
                Log.i("onConnectionStateChange", "Status: " + status);
                switch (newState) {
                    case BluetoothProfile.STATE_CONNECTED:
                        Log.i("gattCallback", "STATE_CONNECTED");
                        gatt.discoverServices();
                        break;
                    case BluetoothProfile.STATE_DISCONNECTED:
                        Log.e("gattCallback", "STATE_DISCONNECTED");

                        break;
                    default:
                        Log.e("gattCallback", "STATE_OTHER");
                }
            }
            catch(Exception ex){
                Log.i("msable","[@@MA] ::::Exception  7" +ex.toString());
                mSecurityCode.setText("[@@MA]Ex7" + ex.toString());
            }

        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            try {
                Log.i("BLE","**** onServicesDiscovered Status: "+status);

                List<BluetoothGattService> services = gatt.getServices();

                for (BluetoothGattService bg : services) {

                    Log.i(bg.toString(), bg.getUuid().toString());

                    if (UUID_MSA_APP.equals(bg.getUuid())) {
                        Log.i("MSA APP", "found");

                        BluetoothGattCharacteristic msacode = bg.getCharacteristics().get(0);
                        //gatt.setCharacteristicNotification(msacode, true);
                        gatt.readCharacteristic(msacode);

                        Log.i("BLE", "**** BluetoothGattCharacteristic msacode: " + msacode.toString());
                    }
                    else{
                        Log.i("MSA APP", "UUID_MSA_APP not Matching found");
                    }
                }
            }
            catch(Exception ex){
                Log.i("msable","[@@MA] ::::Exception  8" +ex.toString());
                mSecurityCode.setText("[@@MA]Ex8" + ex.toString());
            }

        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic
                                                 characteristic, int status) {
            try {
                Log.i("BLE","**** onCharacteristicRead Status: "+status);

                final byte[] data = characteristic.getValue();

                if (data != null && data.length > 0) {
                    final StringBuilder stringBuilder = new StringBuilder(data.length);

                    for (byte byteChar : data)
                        stringBuilder.append(String.format("%02X ", byteChar));

                    Log.i("onCharacteristicRead", new String(data));

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mSecurityCode.setText(new String(data));
                            Intent intent = new Intent(MainActivity.this, newActivity.class);
                            intent.putExtra("UniqueCode", new String(data));
                            startActivity(intent);
                        }
                    });

                }

                gatt.disconnect();


            }
            catch(Exception ex){
                Log.i("msable","[@@MA] ::::Exception  9" +ex.toString());
                mSecurityCode.setText("[@@MA]Ex9" + ex.toString());
            }
        }
    };
}

最佳答案

在回调中需要给 Intent 一个静态上下文并且必须设置 Intent FLAG_ACTIVITY_NEW_TASK 标志。

@Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic
                                                 characteristic, int status) {
            try {

                //Reads the requested characteristic and get the characteristic value.
                final byte[] data = characteristic.getValue();

                if (data != null && data.length > 0) {
                    final StringBuilder stringBuilder = new StringBuilder(data.length);

                    for (byte byteChar : data)
                        stringBuilder.append(String.format("%02X ", byteChar));


                    Intent intent = new Intent(callBackContext, InOutActivity.class);

                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    callBackContext.startActivity(intent);
                }
            }
            catch(Exception ex){
                dbObj.PutLog("[@@MA]EX7" + ex.toString());
            }
            finally{
            if(gatt != null){
            dbObj.PutLog("[MA] 5 CLOSE GATT");
                gatt.disconnect();
                gatt.close();
            }
            }
        }
    };

这里 callBackContext.startActivity(intent); 是给 intent 的静态上下文。这解决了我的目的

关于java - 蓝牙回调函数 onCharacteristicRead 没有对使用 <API 21 的另一个 Activity 进行 Intent 调用。不在 Marshmallow 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39762963/

相关文章:

像 "Interface Builder"这样的 Android 设计器?

android - 使用 TabLayout 和 Navigation Drawer 设置 Fragments

Android 警报管理器 setExactAndAllowWhileIdle() 在打盹模式下的 Android 7.0 Nougat 中不起作用

java - 通过 Intent 将值传递给新 Activity 时遇到问题

java - hibernate 恩弗斯 : Get REVEND_TSTMP from revision entity

java - 在 ""attempts-before"order 示例中,以下 java 程序将如何运行?

java - 将 while 循环嵌套在 do while 循环内

安卓撰写 : Surface can have only one direct measurable child

android - 在没有自动播放的情况下打开视频库

java - audioInputStream 的 url 似乎为空