我有两个活动和一个应用程序类,每当我在其中一个活动中调用我的应用程序类时,程序就会崩溃。以下是两个活动的 onCreate() 方法:
主菜单:
protected BluetoothApplication myBt;
private TextView bluetoothText;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
customTitleSupported = requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView(R.layout.main);
myBt = ((BluetoothApplication)getApplicationContext());
bluetoothText = new TextView(this);
customTitleBar( getText( R.string.app_name).toString(), bluetoothText.getText().toString() );
}
设备列表:
protected BluetoothApplication myBt;
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
// Setup the window
//requestWindowFeature( Window.FEATURE_INDETERMINATE_PROGRESS );
setContentView( R.layout.device_list );
myBt = (BluetoothApplication)getApplicationContext();
// Set result CANCELED in case the use backs out
//setResult( Activity.RESULT_CANCELED );
// Initialize the button to perform device discovery
Button scanButton = (Button) findViewById( R.id.button_scan );
scanButton.setOnClickListener( new OnClickListener() {
public void onClick( View v ) {
doDiscovery();
v.setVisibility( View.GONE );
}
});
// Initialize array adapters. One for already paired devices and one
// for newly discovered devices
mPairedDevicesArrayAdapter = new ArrayAdapter<String>( this, R.layout.device_name );
mNewDevicesArrayAdapter = new ArrayAdapter<String>( this, R.layout.device_name );
// Find and set up the ListView for paired devices
ListView pairedListView = (ListView) findViewById( R.id.paired_devices );
pairedListView.setAdapter( mPairedDevicesArrayAdapter );
pairedListView.setOnItemClickListener( mDeviceClickListener );
// Find and set up the ListView for newly discovered devices
ListView newDevicesListView = (ListView) findViewById( R.id.new_devices );
newDevicesListView.setAdapter( mNewDevicesArrayAdapter );
// 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 = myBt.getMyBtAdapter().getBondedDevices();
if( pairedDevices.size() > 0 ) {
findViewById( R.id.title_paired_devices ).setVisibility( View.VISIBLE );
for ( BluetoothDevice device : pairedDevices ) {
mPairedDevicesArrayAdapter.add( device.getName() + "\n" + device.getAddress() );
}
} else {
String noDevices = getResources().getText( R.string.none_paired ).toString();
mPairedDevicesArrayAdapter.add( noDevices );
}
}
当我删除涉及 BluetoothApplication 的行时,这两个活动都可以正常加载。我尝试将 getApplicationContext() 更改为 getApplication()。
蓝牙应用:
public class BluetoothApplication extends Application {
// Debugging
private static final String TAG = "BluetoothApplication";
private static final boolean D = true;
// Member fields
private BluetoothAdapter myAdapter;
private Handler myHandler;
private BluetoothDevice myBtDevice;
private BluetoothSocket mySocket;
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
private ArrayAdapter<String> mNewDevicesArrayAdapter;
private ConnectThread myConnectThread;
private ConnectedThread myConnectedThread;
private int myState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0;
public static final int STATE_LISTEN = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_CONNECTED = 3;
//In SDK15 (4.0.3) this method is now public as
//Bluetooth.fetchUuisWithSdp() and BluetoothDevice.getUuids()
public ParcelUuid[] servicesFromDevice(BluetoothDevice device) {
try {
Class cl = Class.forName("android.bluetooth.BluetoothDevice");
Class[] par = {};
Method method = cl.getMethod("getUuids", par);
Object[] args = {};
ParcelUuid[] retval = (ParcelUuid[]) method.invoke(device, args);
return retval;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void onCreate( ) {
myAdapter = BluetoothAdapter.getDefaultAdapter();
myAdapter.enable();
}
public BluetoothAdapter getMyBtAdapter() {
return myAdapter;
}
/**
* Set the connection state of the device.
* @param state
*/
public synchronized void setState( int state ) {
if( D ) Log.d(TAG, " setState() " + myState + " -> " + state );
myState = state;
myHandler.obtainMessage( MainMenu.MESSAGE_STATE_CHANGE, state, -1 ).sendToTarget();
}
/**
* Get the connection state.
*/
public synchronized int getState() {
return myState;
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
setState( STATE_NONE );
// Send failure message back to the Activity
Message msg = myHandler.obtainMessage( MainMenu.MESSAGE_TOAST );
Bundle bundle = new Bundle();
bundle.putString( " ", "unable to connect to device" );
msg.setData( bundle );
myHandler.sendMessage( msg );
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
setState( STATE_NONE );
Message msg = myHandler.obtainMessage( MainMenu.MESSAGE_TOAST );
Bundle bundle = new Bundle();
bundle.putString( "ASdasd", "Device connection was lost" );
msg.setData( bundle );
myHandler.sendMessage( msg );
}
public synchronized void start() {
if (D) Log.d(TAG, "start" );
if( myConnectThread != null ) {
myConnectThread.cancel();
myConnectThread = null;
}
if( myConnectedThread != null ) {
myConnectedThread.cancel();
myConnectedThread = null;
}
setState( STATE_NONE );
}
public synchronized void connect( BluetoothDevice device ) {
if( D ) Log.d(TAG, "connect to: " + device );
if( myState == STATE_CONNECTING ) {
if( myConnectThread != null ) { myConnectThread.cancel(); myConnectThread = null;}
}
// Cancel any thread currently running a connection
if( myConnectedThread != null ) {myConnectedThread.cancel(); myConnectedThread = null;}
// Start the thread to connect with the given device
myConnectThread = new ConnectThread( device );
myConnectThread.start();
setState( STATE_CONNECTING );
}
/**
* Start the ConnectedThread to begin managin a Bluetooth connection
*/
public synchronized void connected( BluetoothSocket socket, BluetoothDevice device ) {
if( D ) Log.d(TAG, "connected" );
// Cancel the thread that completed the connection
if( myConnectThread != null ) {
myConnectThread.cancel();
myConnectThread = null;
}
// Cancel any thread currently running a connection
if( myConnectedThread != null ) {
myConnectedThread.cancel();
myConnectedThread = null;
}
// Start the thread to manage the connection and perform transmissions
myConnectedThread = new ConnectedThread( socket );
myConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = myHandler.obtainMessage( MainMenu.MESSAGE_DEVICE_NAME );
Bundle bundle = new Bundle();
bundle.putString( MainMenu.DEVICE_NAME, device.getName() );
msg.setData( bundle );
myHandler.sendMessage( msg );
setState( STATE_CONNECTED );
}
/**
* Stop ALL threads
*/
public synchronized void stop() {
if(D) Log.d( TAG, "stop" );
if( myConnectThread != null ) {
myConnectThread.cancel();
myConnectThread = null;
}
if( myConnectedThread != null ) {
myConnectedThread.cancel();
myConnectedThread = null;
}
setState( STATE_NONE );
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*/
public void write( byte[] out ) {
ConnectedThread r;
synchronized( this ) {
if( myState != STATE_CONNECTED ) return;
r = myConnectedThread;
}
r.write( out );
}
public class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread( BluetoothDevice device ) {
mmDevice = device;
BluetoothSocket tmp = null;
ParcelUuid[] uuids = servicesFromDevice( myBtDevice );
try {
tmp = device.createRfcommSocketToServiceRecord( uuids[0].getUuid() );
} catch (IOException e ) {
Log.e( TAG, "create() failed", e );
}
mmSocket = tmp;
}
public void run() {
Log.i( TAG, "BEGIN mConnectThread" );
setName( "ConnectThread" );
// Always cancel discovery because it will slow down a connection
myAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch ( IOException e ) {
connectionFailed();
try {
mmSocket.close();
} catch ( IOException e2 ) {
Log.e( TAG, "Unable to close() socket during connection failure", e2 );
}
BluetoothApplication.this.start();
return;
}
synchronized ( BluetoothApplication.this ) {
myConnectThread = null;
}
connected( mmSocket, mmDevice );
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e ) {
Log.e( TAG, "close() of connect socket failed", e );
}
}
}
/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread( BluetoothSocket socket ) {
Log.d( TAG, "create ConnectedThread" );
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch ( IOException e ) {
Log.e(TAG, "temp sockets not created", e );
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread" );
byte[] buffer = new byte[1024];
int bytes;
while( true ){
try {
bytes = mmInStream.read( buffer );
myHandler.obtainMessage( MainMenu.MESSAGE_READ, bytes, -1, buffer ).sendToTarget();
} catch (IOException e ) {
Log.e( TAG, "disconnected", e );
connectionLost();
break;
}
}
}
/**
* Write to connected OutStream.
*
*/
public void write( byte[] buffer ) {
try {
mmOutStream.write( buffer );
myHandler.obtainMessage( MainMenu.MESSAGE_WRITE, buffer.length, -1, buffer ).sendToTarget();
} catch ( IOException e ) {
Log.e( TAG, "Exception during write", e );
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e ) {
Log.e( TAG, "close() of connect socket failed", e );
}
}
}
}
我还认为我将 Application 类输入到 Manifest 文件中的方式可能有问题:
修改清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.eti.commander"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name = ".BluetoothApplication" >
<activity
android:name=".MainMenu"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".DeviceList"
android:theme="@android:style/Theme.Dialog"
android:label="@string/devices">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application>
</manifest>
这是 LogCat:
06-18 09:09:26.625: I/Process(2097): Sending signal. PID: 2097 SIG: 9
06-18 09:17:32.241: D/AndroidRuntime(2304): Shutting down VM
06-18 09:17:32.241: W/dalvikvm(2304): threadid=1: thread exiting with uncaught exception (group=0x40015560)
06-18 09:17:32.241: E/AndroidRuntime(2304): FATAL EXCEPTION: main
06-18 09:17:32.241: E/AndroidRuntime(2304): java.lang.RuntimeException: Unable to start activity ComponentInfo{my.eti.commander/my.eti.commander.MainMenu}: java.lang.ClassCastException: android.app.Application
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.os.Handler.dispatchMessage(Handler.java:99)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.os.Looper.loop(Looper.java:130)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.ActivityThread.main(ActivityThread.java:3683)
06-18 09:17:32.241: E/AndroidRuntime(2304): at java.lang.reflect.Method.invokeNative(Native Method)
06-18 09:17:32.241: E/AndroidRuntime(2304): at java.lang.reflect.Method.invoke(Method.java:507)
06-18 09:17:32.241: E/AndroidRuntime(2304): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
06-18 09:17:32.241: E/AndroidRuntime(2304): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
06-18 09:17:32.241: E/AndroidRuntime(2304): at dalvik.system.NativeStart.main(Native Method)
06-18 09:17:32.241: E/AndroidRuntime(2304): Caused by: java.lang.ClassCastException: android.app.Application
06-18 09:17:32.241: E/AndroidRuntime(2304): at my.eti.commander.MainMenu.onCreate(MainMenu.java:47)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
06-18 09:17:32.241: E/AndroidRuntime(2304): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
06-18 09:17:32.241: E/AndroidRuntime(2304): ... 11 more