簡體   English   中英

啟動Intent之前,Android應用程序崩潰

[英]Android app crashes before intent is launched

我正在創建我的第一個android應用程序,所以我真的是(android)開發的初學者。

該應用程序的第一個目的是實現一個Activity(即BleActivity.java),當單擊某個按鈕時將調用該Activity。 BleActivity應該列出可用的BLE設備(使用tiSensorTag CC2650測試),以后我要從設備中讀取數據。

要使其正常工作是一個很大的挑戰,因為大多數在線教程都是使用不推薦使用的API編寫的。 結合了多個教程后,該應用程序現在可以運行了!

應用程序中有一個我無法修復的錯誤:

關閉藍牙並觸發BleActivity時,onResume()檢查是否啟用了藍牙(不是這種情況),如果沒有啟用,則會出現一個對話框,要求用戶打開藍牙。

我可以看到對話框屏幕,但是在我無法使用它之前,應用程序崩潰了。


BleActivity.java

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class BleActivity extends ListActivity {

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    // see nested class LeDeviceListAdapter
    private LeDeviceListAdapter mLeDeviceListAdapter;

    private BluetoothAdapter mBluetoothAdapter;
    private static final int REQUEST_ENABLE_BT = 1;
    private static final long SCAN_PERIOD = 10000;
    private Handler mHandler;
    private boolean mScanning;
    private BluetoothLeScanner mLEScanner;
    private ScanSettings settings;
    private List<ScanFilter> filters;

    private static final String INFO = "ZINFO";

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

        // Check if BLE is supported
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
            finish();
        } else {
            Log.i(INFO, "onCreate: BLE is supported");
        }
        // Create a Handler to send and process Message Class and Runnable objects associated with a thread's MessageQueue.
        mHandler = new Handler();

        // Get BluetoothManager and BluetoothAdapter in order to conduct overall Bluetooth Management.
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
    }

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

        // Initialize list view adapter
        mLeDeviceListAdapter = new LeDeviceListAdapter();
        setListAdapter(mLeDeviceListAdapter);

        //Check if permission for ACCESS_COARSE_LOCATION (AndroidManifest.xml) is granted.
        if (checkLocationPermission()) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, R.string.grant_permission, Toast.LENGTH_LONG).show();
                finish();
            } else {
                Log.i(INFO, "onResume: Permission for ACCESS_COARSE_LOCATION is granted");
            }
        }

        // Check if bluetoothAdapter is successfully obtained and if BLE is enabled.
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        } else {
            Log.i(INFO, "onResume: BLE is enabled");
        }
        // GET getBluetoothLeScanner(): This class provides methods to perform scan related operations for Bluetooth LE devices
        mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
        // Set scan settings
        settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).build();
        // Set device filter (null is allowed)
        filters = new ArrayList<ScanFilter>();

        // START SCAN FOR BLE DEVICES!
        scanLeDevice(true);
    }

    // When user denies prompt for enabling Bluetooth, the Activity is closed
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
                finish();
                return;
            }
        super.onActivityResult(requestCode, resultCode, data);
    }

    // Pause scanning for BLE devices */
    @Override
    protected void onPause() {
        super.onPause();
        scanLeDevice(false);
        mLeDeviceListAdapter.clear();
    }

    //Methods for permission check
    public boolean checkLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
                new AlertDialog.Builder(this)
                        .setTitle(R.string.title_location_permission)
                        .setMessage(R.string.text_location_permission)
                        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                ActivityCompat.requestPermissions(BleActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .create()
                        .show();
            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission. ACCESS_COARSE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);
            }
            return false;
        } else {
            return true;
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.i(INFO, "onRequestPermissionsResult: PERMISSION_GRANTED");
                } else {
                    finish();
                }
            }

        }
    }

    // Methods for START & STOP scan
    private void scanLeDevice(final boolean enable) {
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mLEScanner.stopScan(mScanCallback); //STOP SCANNING
                }
            }, SCAN_PERIOD); // Stops scanning after a pre-defined scan period.

            mScanning = true;
            mLEScanner.startScan(filters, settings, mScanCallback); //START SCANNING
        } else {
            mScanning = false;
            mLEScanner.stopScan(mScanCallback); //STOP SCANNING
        }
        if(mScanning == true) {
            //TODO: Implement code for when the app is scanning (green stoplight, turning wheel, etc.)
        } else {
            //TODO: Implement code for when the app is NOT scanning (red stoplight, idle wheel, etc.)
        }
    }
    // Bluetooth LE scan results are reported using these callbacks.
    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            BluetoothDevice btDevice = result.getDevice();
            mLeDeviceListAdapter.addDevice(btDevice);
            mLeDeviceListAdapter.notifyDataSetChanged();        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            for (ScanResult sr : results) {
                Log.i("ScanResult - Results", sr.toString());
            }
        }
        @Override
        public void onScanFailed(int errorCode) {
            Log.e("Scan Failed", "Error Code: " + errorCode);
        }
    };

    // ListAdapter for holding devices found through scanning.
    private class LeDeviceListAdapter extends BaseAdapter {
        private ArrayList<BluetoothDevice> mLeDevices;
        private LayoutInflater mInflator;

        public LeDeviceListAdapter() {
            super();
            mLeDevices = new ArrayList<BluetoothDevice>();
            mInflator = BleActivity.this.getLayoutInflater();
        }

        public void addDevice(BluetoothDevice device) {
            if(!mLeDevices.contains(device)) {
                mLeDevices.add(device);
            }
        }

        /*
        TODO: implement onListItemClick (see example code)
        public BluetoothDevice getDevice(int position) {
            return mLeDevices.get(position);
        }*/

        public void clear() {
            mLeDevices.clear();
        }

        @Override
        public int getCount() {
            return mLeDevices.size();
        }

        @Override
        public Object getItem(int i) {
            return mLeDevices.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            // General ListView optimization code.
            if (view == null) {
                view = mInflator.inflate(R.layout.activity_ble, null);
                viewHolder = new ViewHolder();
                viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
                viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            BluetoothDevice device = mLeDevices.get(i);
            final String deviceName = device.getName();
            if (deviceName != null && deviceName.length() > 0)
                viewHolder.deviceName.setText(deviceName);
            else
                viewHolder.deviceName.setText(R.string.unknown_device);
                viewHolder.deviceAddress.setText(device.getAddress());

            return view;
        }
    }
    static class ViewHolder {
        TextView deviceName;
        TextView deviceAddress;
    }
}

非常感謝您的幫助,請記住,這是我的第一個應用程序,我仍然是業余/初學者開發人員。


logcat的:

08-06 16:21:39.152 5489-5489/nl.cargosys.iotcloudconnect E/AndroidRuntime: FATAL EXCEPTION: main
                                                                           Process: nl.cargosys.iotcloudconnect, PID: 5489
                                                                           java.lang.RuntimeException: Unable to pause activity {nl.cargosys.iotcloudconnect/nl.cargosys.iotcloudconnect.BleActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.le.BluetoothLeScanner.stopScan(android.bluetooth.le.ScanCallback)' on a null object reference
                                                                               at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4179)
                                                                               at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4145)
                                                                               at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4119)
                                                                               at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4093)
                                                                               at android.app.ActivityThread.-wrap18(ActivityThread.java)
                                                                               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1654)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                               at android.os.Looper.loop(Looper.java:154)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:6776)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
                                                                            Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.le.BluetoothLeScanner.stopScan(android.bluetooth.le.ScanCallback)' on a null object reference
                                                                               at nl.cargosys.iotcloudconnect.BleActivity.scanLeDevice(BleActivity.java:179)
                                                                               at nl.cargosys.iotcloudconnect.BleActivity.onPause(BleActivity.java:121)
                                                                               at android.app.Activity.performPause(Activity.java:7148)
                                                                               at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1330)
                                                                               at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4168)
                                                                               at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4145) 
                                                                               at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4119) 
                                                                               at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4093) 
                                                                               at android.app.ActivityThread.-wrap18(ActivityThread.java) 
                                                                               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1654) 
                                                                               at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                               at android.os.Looper.loop(Looper.java:154) 
                                                                               at android.app.ActivityThread.main(ActivityThread.java:6776) 
                                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) 
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410) 

在下面的if條件下-

if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) 

主要問題在於-

mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
    // Set scan settings
    settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).build();
    // Set device filter (null is allowed)
    filters = new ArrayList<ScanFilter>();

    // START SCAN FOR BLE DEVICES!
    scanLeDevice(true);

您檢查適配器是否可用,如果不是,則啟動另一個活動以獲取結果,但是繼續在掃描儀代碼中進行操作,然后在其他操作之后掃描設備。 理想情況下,應將以上代碼放在else語句中,僅在100%確定已啟用藍牙的情況下才開始掃描設備。

更新1

好的,所以此錯誤來自於您在調用scanLeDevice(false); onPause()方法中scanLeDevice(false); 方法。 現在,在此方法中,執行mLEScanner.stopScan(mScanCallback); 但是您的mLEScanner尚未初始化,因為初始化代碼在您的else語句中或該行之后

mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();

因此,如果您以自己的方法執行此操作,則更好-

if(mLEScanner!=null)
{
   mLEScanner.stopScan(mScanCallback); 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM