ClassCastException导致我的程序崩溃

时间:2012-06-18 13:25:44

标签: android singleton

我有两个活动和一个Application类,每当我在其中一个活动中调用我的Application类时程序崩溃。以下是两个活动的onCreate()方法:

的MainMenu:

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() );
}

DEVICELIST:

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()。

BluetoothApplication:

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

3 个答案:

答案 0 :(得分:1)

问题可能是,您的活动是在与蓝牙应用程序不同的应用程序中声明的。现在的方式是,活动的应用程序不会声明隐式类,因此使用默认的Application类。然后,您尝试将其转换为您的活动中的BluetoothApplication,它根本就不是。

尝试清除清单中的第二个应用程序标记并添加android:name =&#34; BluetoothApplication&#34;到第一个应用程序标签。

答案 1 :(得分:1)

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >

你应该在这里添加

android:name=".BluetoothApplication"

让操作系统知道你有自己的应用程序类。 另外,删除此块:

<application
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:name="BluetoothApplication">
</application>

答案 2 :(得分:1)

您忘记在清单文件中提供应用程序名称。您的清单文件中还有两个应用程序标记,(删除第二个)

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" 
    android:name=".BluetoothApplication"
>

并删除最后一个应用程序节点

<application
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:name="BluetoothApplication">
</application>