扩展类时为什么会得到ClassCastException?

时间:2018-11-21 07:57:15

标签: java android

我正在开发一个可以从Bluetooth RFID阅读器读取数据的应用程序,但是每次我启动BluetoothActivity(这是一个选项卡式活动)时,它始终显示ClassCastException,下面是我的代码。

BluetoothActivity类:

package com.siscaproject.sisca.Activity;

import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import android.widget.TextView;

import com.siscaproject.sisca.Fragment.RegisterFragment;
import com.siscaproject.sisca.Fragment.SearchFragment;
import com.siscaproject.sisca.R;
import com.siscaproject.sisca.Utilities.FamsModel;
import com.siscaproject.sisca.Utilities.TSLBluetoothDeviceActivity;
import com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
import com.uk.tsl.rfid.asciiprotocol.responders.LoggerResponder;

import java.util.ArrayList;

import butterknife.BindView;
import butterknife.ButterKnife;

public class BluetoothActivity extends TSLBluetoothDeviceActivity {
    private SectionsPagerAdapter mSectionsPagerAdapter;

    @BindView(R.id.viewpager_bluetooth) ViewPager mViewPager;
    @BindView(R.id.toolbar_bluetooth) Toolbar mToolbar;
    @BindView(R.id.tab_bluetooth) TabLayout mTabLayout;

    private FamsModel mModel;


    public AsciiCommander getCommander(){
        return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
    }


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

        ButterKnife.bind(this);

        setSupportActionBar(mToolbar);
        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        setupViewPager(mViewPager);

        mTabLayout.setupWithViewPager(mViewPager);

        AsciiCommander commander = getCommander();

        // Add the LoggerResponder - this simply echoes all lines received from the reader to the log
        // and passes the line onto the next responder
        // This is added first so that no other responder can consume received lines before they are logged.
        commander.addResponder(new LoggerResponder());

        // Add a synchronous responder to handle synchronous commands
        commander.addSynchronousResponder();


    }

    private void setupViewPager(ViewPager viewPager){
        SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new RegisterFragment(), "REGISTER");
        adapter.addFragment(new SearchFragment(), "SEARCH");
        viewPager.setAdapter(adapter);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_bluetooth, 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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.menu_item_reconnect_reader) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SECTION_NUMBER = "section_number";

        public PlaceholderFragment() {
        }

        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_bluetooth, container, false);
            TextView textView = (TextView) rootView.findViewById(R.id.section_label);
            textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
            return rootView;
        }
    }

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        private ArrayList<Fragment> fragmentList = new ArrayList<>();
        private ArrayList<String> fragmentTitleList = new ArrayList<>();

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return fragmentList.size();
        }

        public void addFragment(Fragment fragment, String title ){
            fragmentList.add(fragment);
            fragmentTitleList.add(title);
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return fragmentTitleList.get(position);
        }
    }
}

TSLBluetoothDeviceActivity类:

package com.siscaproject.sisca.Utilities;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

import com.siscaproject.sisca.BuildConfig;
import com.uk.tsl.rfid.DeviceListActivity;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;

import java.util.Timer;
import java.util.TimerTask;

public class TSLBluetoothDeviceActivity extends AppCompatActivity {
    // Debugging
    private static final String TAG = "TSLBTDeviceActivity";
    private static final boolean D = BuildConfig.DEBUG;

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
    private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
    private static final int REQUEST_ENABLE_BT = 3;

    // Local Bluetooth adapter
    private BluetoothAdapter mBluetoothAdapter = null;
    private BluetoothDevice mDevice = null;

    protected AsciiCommander getCommander() {
        return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // Create the AsciiCommander to talk to the reader (if it doesn't already exist)
        if (getCommander() == null) {
            try {
                TSLBluetoothDeviceApplication app = (TSLBluetoothDeviceApplication) getApplication();
                AsciiCommander commander = new AsciiCommander(getApplicationContext());
                app.setCommander(commander);

            } catch (Exception e) {
                fatalError("Unable to create AsciiCommander!");
            }
        }
    }


    // Terminate the app with the given message
    private void fatalError(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
        Timer t = new Timer();
        t.schedule(new TimerTask() {
            public void run() {
                finish();
            }
        }, 1800);
    }

    protected void bluetoothNotAvailableError(String message) {
        fatalError(message);
    }


    @Override
    public void onStart() {
        super.onStart();

        // If no other attempt to connect is ongoing try to connect to last used reader
        // Note: When returning from the Device List activity
        if (mBluetoothAdapter.isEnabled()) {
            if (mDevice == null) {
                // Attempt to reconnect to the last reader used
                Toast.makeText(this, "Reconnecting to last used reader...", Toast.LENGTH_SHORT).show();

                getCommander().connect(null);
            }
        } else {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
    }

    @Override
    public void onStop() {
        super.onStop();

        getCommander().disconnect();
        mDevice = null;
    }

    protected void connectToDevice(Intent deviceData, boolean secure) {
        Toast.makeText(this.getApplicationContext(), "Connecting...", Toast.LENGTH_LONG).show();
        // Get the device MAC address
        String address = deviceData.getExtras()
                .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
        // Get the BluetoothDevice object
        mDevice = mBluetoothAdapter.getRemoteDevice(address);
        // Attempt to connect to the device
        if (mDevice != null) {
            getCommander().connect(mDevice);
        } else {
            if (D) Log.e(TAG, "Unable to obtain BluetoothDevice!");
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (D)
            Log.d(TAG, "selectDevice() onActivityResult: " + resultCode + " for request: " + requestCode);

        switch (requestCode) {
            case REQUEST_CONNECT_DEVICE_SECURE:
                // When DeviceListActivity returns with a device to connect
                if (resultCode == Activity.RESULT_OK) {
                    connectToDevice(data, true);
                }
                break;
            case REQUEST_CONNECT_DEVICE_INSECURE:
                // When DeviceListActivity returns with a device to connect
                if (resultCode == Activity.RESULT_OK) {
                    connectToDevice(data, false);
                }
                break;
            case REQUEST_ENABLE_BT:
                // When the request to enable Bluetooth returns
                if (resultCode != Activity.RESULT_OK) {
                    // User did not enable Bluetooth or an error occurred
                    Log.d(TAG, "BT not enabled");
                    bluetoothNotAvailableError("Bluetooth was not enabled\nApplication Quitting...");
                }
        }
    }


    public void selectDevice() {
        // Launch the DeviceListActivity to see devices and do scan
        Intent serverIntent = new Intent(this, DeviceListActivity.class);
        startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
    }

    public void disconnectDevice() {
        mDevice = null;
        getCommander().disconnect();
    }

    public void reconnectDevice() {
        getCommander().connect(null);
    }
}

错误日志:

11-21 14:47:54.836 18956-18956/com.siscaproject.sisca E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.siscaproject.sisca, PID: 18956
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.siscaproject.sisca/com.siscaproject.sisca.Activity.BluetoothActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2318)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396)
        at android.app.ActivityThread.access$800(ActivityThread.java:139)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:149)
        at android.app.ActivityThread.main(ActivityThread.java:5257)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication
        at com.siscaproject.sisca.Activity.BluetoothActivity.getCommander(BluetoothActivity.java:51)
        at com.siscaproject.sisca.Utilities.TSLBluetoothDeviceActivity.onCreate(TSLBluetoothDeviceActivity.java:45)
        at com.siscaproject.sisca.Activity.BluetoothActivity.onCreate(BluetoothActivity.java:57)
        at android.app.Activity.performCreate(Activity.java:5411)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396) 
        at android.app.ActivityThread.access$800(ActivityThread.java:139) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:149) 
        at android.app.ActivityThread.main(ActivityThread.java:5257) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609) 
        at dalvik.system.NativeStart.main(Native Method) 

我从运行良好的应用程序中遵循了此代码,但是当我在项目中实现该代码时,它始终显示此错误,我不确定自己在做什么错。

---编辑---

TSLBluetoothDeviceApplication类:

package com.siscaproject.sisca.Utilities;

import android.app.Application;

import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;


public class TSLBluetoothDeviceApplication extends Application {
    private static AsciiCommander commander = null;

    /// Returns the current AsciiCommander
    public AsciiCommander getCommander() {
        return commander;
    }

    /// Sets the current AsciiCommander
    public void setCommander(AsciiCommander _commander) {
        commander = _commander;
    }

}

Android清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.siscaproject.sisca">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:replace="android:icon">
        <activity
            android:name=".Activity.LoginActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Activity.BluetoothTestActivity"
            android:theme="@style/StandardTheme" />
        <activity
            android:name=".Activity.HomeActivity"
            android:label="@string/title_activity_home"
            android:theme="@style/AppTheme" />

        <meta-data
            android:name="com.google.android.gms.vision.DEPENDENCIES"
            android:value="barcode" />

        <activity android:name=".Activity.QRActivity" />
        <activity
            android:name=".Activity.BluetoothActivity"
            android:label="@string/title_activity_bluetooth"
            android:theme="@style/AppTheme"></activity>
    </application>

</manifest>

2 个答案:

答案 0 :(得分:2)

活动内的

getApplication()返回类型为Application的对象。在您的情况下,您试图将此对象转换为TSLBluetoothDeviceApplication类型类的Activity

如我所见,您正在尝试调用TSL活动类中已定义的getCommander()。我假设您要使用另一类的getCommander()方法。确保是哪个方法。

public AsciiCommander getCommander(){
    return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}

该方法已经在TSLBluetoothDeviceApplication类中。.我不知道您试图通过调用当前类中已经存在的相同方法来实现什么。

编辑:

编辑完帖子后,我们注意到该类已正确实现,只是忘了添加 android:name="com.path.to.ApplicationClass"放入Manifest标签下的<application/>文件中。

我也会让上面的答案,因为它可能会帮助其他人 快乐编码<3

答案 1 :(得分:1)

很明显,没有使用您的应用程序类。您需要像这样将其添加到xml Application标签中:

 <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication"
    android:theme="@style/AppTheme"
    tools:replace="android:icon">

唯一的变化是将android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication"作为自定义类添加到Application标签。