0

I've read previous threads about this issue but the answers couldn't solve my problem. I have a BroadcastReceiver which is an inner class inside MainActivity that fails with the following exception:

java.lang.RuntimeException: Unable to instantiate receiver com.tac.kulik.dealsgrabber.MainActivity$DatabaseBroadcastReceiver: java.lang.InstantiationException: can't instantiate class com.tac.kulik.dealsgrabber.MainActivity$DatabaseBroadcastReceiver; no empty constructor at android.app.ActivityThread.handleReceiver(ActivityThread.java:2410) at android.app.ActivityThread.access$1700(ActivityThread.java:142) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1279) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5118) 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:794) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:610) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.InstantiationException: can't instantiate class com.tac.kulik.dealsgrabber.MainActivity$DatabaseBroadcastReceiver; no empty constructor at java.lang.Class.newInstanceImpl(Native Method) at java.lang.Class.newInstance(Class.java:1214) at android.app.ActivityThread.handleReceiver(ActivityThread.java:2405) at android.app.ActivityThread.access$1700(ActivityThread.java:142)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1279)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:136)  at android.app.ActivityThread.main(ActivityThread.java:5118)  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:794)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:610)  at dalvik.system.NativeStart.main(Native Method) 

Making the BroadcastReceiver static is not an option as I will not have access to necessary member variables I need to use.

Here is MainActivity with the BroadcastReceiver inner class:

public class MainActivity extends AppCompatActivity {

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

    try {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent dbIntent = new Intent(MainActivity.this, DatabaseBroadcastReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, dbIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmManager.INTERVAL_DAY, pendingIntent);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public class DatabaseBroadcastReceiver extends BroadcastReceiver {

    public DatabaseBroadcastReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        final Context mContext = context;

        .
        .
        .
        .
        .

            @Override
            public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
                Log.d(TAG, "onLoadFinished s=" + cursor.getCount());

                mDealsAdapter.swapCursor(cursor);
            }

            @Override
            public void onLoaderReset(Loader<Cursor> arg0) {
                Log.d(TAG, "onLoaderReset");
                mDealsAdapter.swapCursor(null);
            }
        };
        getSupportLoaderManager().initLoader(0, new Bundle(), mCallback);
    }
};

AndroidManifest.xml

<receiver android:name=".MainActivity$DatabaseBroadcastReceiver"/>

Please advise anyone.

Lior L
  • 49
  • 1
  • 1
  • 7

1 Answers1

1

Making the BroadcastReceiver static is not an option as I will not have access to necessary member variables I need to use.

Then that is a bug in your app, and you will need to fix that bug.

Your entire process, let alone the activity, will not exist when the alarm goes off, in all likelihood. Your BroadcastReceiver needs to be able to work completely independently of the activity. Typically, such a receiver is implemented as a top-level public Java class, to help enforce such independence.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • ok, but why does it say "no empty constructor" while I do have an empty constructor? – Lior L Feb 27 '17 at 07:39
  • @LiorL: Because it is not a `static` class or standalone public class. The only thing that can create an instance of your receiver is your activity. In particular, framework classes cannot create an instance of your receiver. – CommonsWare Feb 27 '17 at 12:34
  • 1
    @LiorL Technically your inner class has an empty constructor. However, because it is not declared as `static`, the compiler actually generates a single-argument constructor out of your empty constructor. The single argument is the instance of the surrounding outer class. A non-static inner class implicitly has a member variable which is a reference to the instance of the surrounding outer class. – David Wasser Feb 28 '17 at 09:58