简体   繁体   English

为什么在扩展类时会出现ClassCastException?

[英]Why do I get ClassCastException when I extend a class?

I'm developing an app which can read data from a Bluetooth RFID Reader, but everytime i start the BluetoothActivity (it's a tabbed activity), it always shows a ClassCastException, below is my code.. 我正在开发一个可以从蓝牙RFID阅读器读取数据的应用程序,但每次我启动蓝牙活动(它是一个标签式活动),它总是显示一个ClassCastException,下面是我的代码..

BluetoothActivity class: 蓝牙活动类:

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 class: 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);
    }
}

The error log: 错误日志:

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) 

I've followed this code from an app that works fine, but when I implemented it in my project it always shows this error, I'm not sure what I'm doing wrong. 我从一个工作正常的应用程序中跟踪了这个代码,但是当我在我的项目中实现它时,它总是显示这个错误,我不确定我做错了什么。

---EDIT--- - -编辑 - -

TSLBluetoothDeviceApplication class: 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 Manifest: 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>

getApplication() inside an activity returns an object of type Application . getApplication()返回Application类型的对象。 In your case you are trying to cast this object into TSLBluetoothDeviceApplication which, as defined by you, is an Activity type class. 在您的情况下,您尝试将此对象转换为TSLBluetoothDeviceApplication ,根据您的定义,它是一个Activity类型类。

As I see, you are trying to call getCommander() which is defined already in your TSL activity class. 正如我所见,您正在尝试调用已在TSL活动类中定义的getCommander() I assume you want getCommander() method from another class.. Make sure which one is. 我假设你想从另一个类中获取getCommander()方法。确保哪一个是。

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

This method is already inside TSLBluetoothDeviceApplication class.. I don't know what are you trying to achieve by trying to call same method which is already in your current class. 这个方法已经在TSLBluetoothDeviceApplication类中。我不知道你试图通过尝试调用当前类中已有的同一方法来实现什么。

EDIT: 编辑:

After the edited post, we noticed that the class was properly implemented, just forgot to add android:name="com.path.to.ApplicationClass" into the Manifest file under <application/> tag. 在编辑后的帖子之后,我们注意到该类已正确实现,只是忘了将android:name="com.path.to.ApplicationClass"<application/>标记下的Manifest文件中。

I will let the above answer also, because it may help others Happy coding <3 我也会让上面的答案,因为它可能会帮助别人快乐编码<3

It's clear that your application class is not used. 很明显,您的应用程序类未被使用。 You need to add it to your xml Application tag like this: 您需要将它添加到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">

and the only change is adding android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication" to the Application tag as your customized class. 唯一的变化是将android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication"作为自定义类添加到Application标记中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM