Android 蓝牙应用在启动时崩溃

Android bluetooth app crashing on startup

当应用程序首次启动时,它会在启动时立即崩溃。我已将问题缩小到一行,但不确定该怎么做 =/ 到目前为止,这是应用程序中的两个 classes:

package com.example.bluetooth_app;

import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class Bluetooth {
    private BluetoothAdapter mBluetoothAdapter;
    private Activity activity; //Activity to store main window's activity
    private ArrayAdapter<String> pDevices; //Array adapter for storing already paired devices
    private ArrayAdapter<String> nDevices; //Array adapter for storing newly discovered devices
    private IntentFilter filter; //Filter for catching bluetooth device actions
    private Button sButton; //Scan button
    private ListView lvBox; //listview box

    /**
     * default constructor, basic initializations
     */
    public Bluetooth(Activity activity) {
        this.activity = activity; //Set class activity to the activity passed to it by the main activity window
        pDevices = new ArrayAdapter<String>(activity, R.layout.activity_bluetooth__app);
        nDevices = new ArrayAdapter<String>(activity, R.layout.activity_bluetooth__app);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        sButton = (Button) activity.findViewById(R.id.scanButton); //sButton = scan button
        sButton.setOnClickListener(new View.OnClickListener() { //Listener to check if button is pressed
            public void onClick(View v) { //If button is pressed start discovering and hide button
                startDiscovering();
                sButton.setVisibility(4); //Make button invisible
            }
        });

        lvBox = (ListView) activity.findViewById(R.id.deviceList); // lvBox = deviceList listview
        lvBox.setAdapter(pDevices);


        // Register for broadcasts when a device is discovered
        filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        activity.registerReceiver(mReceiver, filter);

        // Register for broadcasts when discovery has finished
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        activity.registerReceiver(mReceiver, filter);
    }

    /**
     * Check if bluetooth is enabled, if not enable it
     */
    public void getAdapter() {
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            activity.startActivityForResult(enableBtIntent, 1);
        }

    }

    /**
     * Check if device is bluetooth compatible
     */
    public boolean isCompat() {
        if(mBluetoothAdapter == null) {
            return false; //TODO: better error handling
        } else {
            return true;
        }
    }

    /**
     * Close some shit so we do not eat up resources
     */
    public void destroy() { 
        if(mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery(); //cancel discovering devices
        }

        activity.unregisterReceiver(mReceiver);
    }

    /**
     * Start discovering devices with bluetooth adapter
     */
    public void startDiscovering() {
        if(mBluetoothAdapter.isDiscovering()) {
            mBluetoothAdapter.cancelDiscovery();
        }

        mBluetoothAdapter.startDiscovery();
    }

    public void pairedDevices() {
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        // If there are paired devices
        if (pairedDevices.size() > 0) {
            sButton.setText("found some");
            // Loop through paired devices
            for (BluetoothDevice device : pairedDevices) {
                // Add the name and address to an array adapter to show in a ListView
                pDevices.add(device.getName() + "\n" + device.getAddress());
            }
        }
    }

    /**
     * The BroadcastReceiver that listens for discovered devices and changes the title when
     * discovery is finished
     */
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // If it's already paired, skip it, because it's been listed already
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    nDevices.add(device.getName() + "\n" + device.getAddress());
                }
                // When discovery is finished, change the Activity title
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                sButton.setVisibility(0); //Make button visible again
                if (nDevices.getCount() == 0) {
                    sButton.setText("none");
                    //TODO: none found do something
                }
            }
        }
    };

}

和:

package com.example.bluetooth_app;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

import com.example.bluetooth_app.Bluetooth;

public class Bluetooth_App extends ActionBarActivity {
    private Bluetooth bT;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bluetooth__app);

        bT = new Bluetooth(this);

        bT.isCompat();
        bT.getAdapter();
        bT.pairedDevices();
    }

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

        bT.destroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.bluetooth__app, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

问题出在第一个 class 这一行:lvBox.setAdapter(pDevices);,如果我将其注释掉它运行得很好,否则它会在启动时崩溃。任何帮助将不胜感激 - 谢谢。

EDIT1 - 不,它有一个名为 deviceList 的列表视图,XML 文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.bluetooth_app.Bluetooth_App" >

    <Button
        android:id="@+id/scanButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="28dp"
        android:layout_marginTop="21dp"
        android:text="Scan" />

    <ListView
        android:id="@+id/deviceList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/button1"
        android:layout_below="@+id/button1"
        android:layout_marginRight="26dp"
        android:layout_marginTop="48dp" >
    </ListView>

</RelativeLayout>

请注意,在 Bluetooth_App 中初始化 ArrayAdapter 时,您似乎重复使用了 activity 的布局文件 R.layout.activity_bluetooth__app。这可能不是您的本意。传递给 ArrayAdapter 构造函数的资源应该表示单个 AdapterView 行的布局,并且必须包含一个 TextView 和 id text1(要使用更自定义的行布局,你需要继承 ArrayAdapter 并覆盖 getView).