我有一个问题,我现在花了 2 周时间试图解决。我会尽量详细,但如果有不清楚的地方,请询问。我正在开发一个蓝牙聊天应用程序。一切正常,除了导致崩溃的 4 行代码。我做了一个次要活动,当你点击连接时你会被发送。
这是布局(connection_activity.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="@+id/title_paired_devices"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/title_paired_devices"
android:visibility="gone"
android:background="#666"
android:textColor="#fff"
android:paddingLeft="5dp"
/>
<ListView android:id="@+id/paired_devices"
android:textIsSelectable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stackFromBottom="true"
android:layout_weight="1"
/>
<TextView android:id="@+id/title_new_devices"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/title_other_devices"
android:visibility="gone"
android:background="#666"
android:textColor="#fff"
android:paddingLeft="5dp"
/>
<ListView android:id="@+id/new_devices"
android:textIsSelectable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stackFromBottom="true"
android:layout_weight="2"
/>
<Button android:id="@+id/button4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button_scan"
/>
</LinearLayout>
这只是一个简单的活动,有 2 个列表来显示已配对和可用的设备(可单击它们以连接其中一个)。
然后是源代码(ConnectionActivity.java)
/* In this activity I will manage the secondary layout (for bluetooth connection)*/
package com.andrecl.interapption;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class ConnectionActivity extends Activity implements OnClickListener {
/* Initializing part */
BluetoothAdapter mBluetoothAdapter;
BluetoothSocket mSocket;
BluetoothDevice mDevice;
public static String EXTRA_DEVICE_ADDRESS = "device_address"; // this is the
// number
// code of
// the
// devices
Button scanButton; //the scan button
StartDiscover startDiscover; //start discover thread
/* For intent request */
private static final int REQUEST_ENABLE_BT = 1;
/* Arrays for storing the lists of paired devices and found devices */
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
private ArrayAdapter<String> mNewDevicesArrayAdapter;
/* Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.connection_activity);
// Get the local Bluetooth adapter (as in the other activity)
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
/* Make sure bt is on! */
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
/* Initialize array adapters. One for already paired devices and one for newly discovered devices */
mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.connection_activity);
mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.connection_activity);
/* Find and set up the ListView for paired devices */
ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
pairedListView.setAdapter(mPairedDevicesArrayAdapter);
pairedListView.setOnItemClickListener(mDeviceClickListener); //later implemented if you click on a device
/* Find and set up the ListView for newly discovered devices */
ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
newDevicesListView.setOnItemClickListener(mDeviceClickListener); //later implemented if you click on a device
// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
/*Finally we start listening if the scanbutton is pressed*/
startDiscover = new StartDiscover();
scanButton = (Button) findViewById(R.id.button4);
scanButton.setOnClickListener(this);
/* List of paired devices */ //removed the array printing due to crash
if (pairedDevices.size() > 0) {
findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
Toast.makeText(this, "Paired devices", Toast.LENGTH_SHORT).show();
mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
} else {
Toast.makeText(this, "No paired devices", Toast.LENGTH_SHORT).show();
String noDevices = getResources().getText(R.string.none_paired).toString();
mPairedDevicesArrayAdapter.add(noDevices);
}
}
/* The scan button */
public void onClick(View v) {
startDiscover.start();
v.setVisibility(View.GONE); // so you can't use the button again (avoid Button spamming). GONE: This view is invisible, and it doesn't take any space for layout purposes
}
/*The Discover thread*/
private class StartDiscover extends Thread{
private Handler dHandler = new Handler();
public void run(){
dHandler.post(new Runnable(){
public void run(){
mBluetoothAdapter.startDiscovery();
toast();
}
});
}
}
public void toast(){
Toast.makeText(this, "Scanning - Please wait", Toast.LENGTH_SHORT).show();
}
// 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 DEACTIVATED DUE TO CRASH
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setTitle(R.string.select_device); //Due to space issues, the instructions are displayed in the title.
/*If no devices found ... removed due to crashing*/
if (mNewDevicesArrayAdapter.getCount() == 0) {
String noDevices = getResources().getText(R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
// Make sure we're not doing discovery anymore
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
// Unregister broadcast listeners
this.unregisterReceiver(mReceiver);
}
// The on-click listener for all devices in the ListViews
private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
// Cancel discovery because it's costly and we're about to connect
mBluetoothAdapter.cancelDiscovery();
// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) v).getText().toString();
String address = info.substring(info.length() - 17);
// Create the result Intent and include the MAC address
Intent intent = new Intent();
intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
// Set result and finish this Activity
setResult(Activity.RESULT_OK, intent);
finish();
}
};
}
现在是什么导致整个应用程序崩溃(如果我删除这些行它不会崩溃)是: mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); 和 mPairedDevicesArrayAdapter.add(noDevices);
后来 mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); 和 mNewDevicesArrayAdapter.add(noDevices);
这四行似乎是问题所在。有没有人能够识别我做错了什么?
谢谢你的时间,
编辑:我很抱歉,这里是 LogCat:
05-22 19:25:27.592: D/libEGL(27711): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
05-22 19:25:27.600: D/libEGL(27711): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
05-22 19:25:27.600: D/libEGL(27711): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
05-22 19:25:27.787: D/OpenGLRenderer(27711): Enabling debug mode 0
05-22 19:25:30.928: D/OpenGLRenderer(27711): Flushing caches (mode 0)
05-22 19:25:44.225: E/ArrayAdapter(27711): You must supply a resource ID for a TextView
05-22 19:25:44.225: D/AndroidRuntime(27711): Shutting down VM
05-22 19:25:44.225: W/dalvikvm(27711): threadid=1: thread exiting with uncaught exception (group=0x40bfc1f8)
05-22 19:25:44.233: E/AndroidRuntime(27711): FATAL EXCEPTION: main
05-22 19:25:44.233: E/AndroidRuntime(27711): java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:386)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.ArrayAdapter.getView(ArrayAdapter.java:362)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.AbsListView.obtainView(AbsListView.java:2210)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.ListView.measureHeightOfChildren(ListView.java:1244)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.ListView.onMeasure(ListView.java:1155)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.View.measure(View.java:12775)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4709)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1385)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.LinearLayout.measureVertical(LinearLayout.java:670)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.LinearLayout.onMeasure(LinearLayout.java:563)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.View.measure(View.java:12775)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4709)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.View.measure(View.java:12775)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.LinearLayout.measureVertical(LinearLayout.java:822)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.LinearLayout.onMeasure(LinearLayout.java:563)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.View.measure(View.java:12775)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4709)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
05-22 19:25:44.233: E/AndroidRuntime(27711): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2240)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.View.measure(View.java:12775)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1117)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2505)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.os.Handler.dispatchMessage(Handler.java:99)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.os.Looper.loop(Looper.java:137)
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.app.ActivityThread.main(ActivityThread.java:4514)
05-22 19:25:44.233: E/AndroidRuntime(27711): at java.lang.reflect.Method.invokeNative(Native Method)
05-22 19:25:44.233: E/AndroidRuntime(27711): at java.lang.reflect.Method.invoke(Method.java:511)
05-22 19:25:44.233: E/AndroidRuntime(27711): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
05-22 19:25:44.233: E/AndroidRuntime(27711): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
05-22 19:25:44.233: E/AndroidRuntime(27711): at dalvik.system.NativeStart.main(Native Method)
05-22 19:25:44.233: E/AndroidRuntime(27711): Caused by: java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.TextView
05-22 19:25:44.233: E/AndroidRuntime(27711): at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:379)
05-22 19:25:44.233: E/AndroidRuntime(27711): ... 30 more
05-22 19:26:44.717: I/Process(27711): Sending signal. PID: 27711 SIG: 9