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