cleanrun
cleanrun

Reputation: 746

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..

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:

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:

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:

<?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>

Upvotes: 1

Views: 218

Answers (2)

Khalid Taha
Khalid Taha

Reputation: 3313

It's clear that your application class is not used. You need to add it to your xml Application tag like this:

 <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.

Upvotes: 1

Ionut J. Bejan
Ionut J. Bejan

Reputation: 754

getApplication() inside an activity returns an object of type Application. In your case you are trying to cast this object into TSLBluetoothDeviceApplication which, as defined by you, is an Activity type class.

As I see, you are trying to call getCommander() which is defined already in your TSL activity class. I assume you want getCommander() method from another class.. Make sure which one is.

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.

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 Manifestfile under <application/> tag.

I will let the above answer also, because it may help others Happy coding <3

Upvotes: 2

Related Questions