6

My emulators :

emulators

When I launch the tablet emulator I get :

FATAL EXCEPTION: main
java.lang.IllegalArgumentException: Component class TriggerMonitoringBootReceiver does not exist in di.k23b.hw3
    at android.os.Parcel.readException(Parcel.java:1429)
    at android.os.Parcel.readException(Parcel.java:1379)
    at android.content.pm.IPackageManager$Stub$Proxy.setComponentEnabledSetting(IPackageManager.java:2561)
    at android.app.ApplicationPackageManager.setComponentEnabledSetting(ApplicationPackageManager.java:1250)
    at di.k23b.hw3.receivers.TriggerMonitoringBootReceiver.enable(TriggerMonitoringBootReceiver.java:81)
    at di.k23b.hw3.receivers.TriggerMonitoringBootReceiver.enable(TriggerMonitoringBootReceiver.java:86)
    at di.k23b.hw3.activities.SettingsActivity.onSharedPreferenceChanged(SettingsActivity.java:192)
    at android.app.SharedPreferencesImpl$EditorImpl.notifyListeners(SharedPreferencesImpl.java:475)
    at android.app.SharedPreferencesImpl$EditorImpl.apply(SharedPreferencesImpl.java:385)
    at android.preference.Preference.tryCommit(Preference.java:1349)
    at android.preference.Preference.persistBoolean(Preference.java:1615)
    at android.preference.TwoStatePreference.setChecked(TwoStatePreference.java:83)
    at android.preference.TwoStatePreference.onClick(TwoStatePreference.java:69)
    at android.preference.Preference.performClick(Preference.java:949)
    at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:215)
    at android.widget.AdapterView.performItemClick(AdapterView.java:298)
    at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
    at android.widget.AbsListView$PerformClick.run(AbsListView.java:2749)
    at android.widget.AbsListView$1.run(AbsListView.java:3423)
    at android.os.Handler.handleCallback(Handler.java:725)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5041)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    at dalvik.system.NativeStart.main(Native Method)

When I launch the froyo emulator all is fine (EDIT : no it is not - the receiver is not enabled BUT still there is no crash).
Is it a known issue or something ?

Manifest :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="di.k23b.hw3"
    android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
    <application android:allowBackup="true" android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" android:theme="@style/AppTheme" >
        <activity
            android:name="di.k23b.hw3.activities.MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="di.k23b.hw3.activities.SettingsActivity"
            android:label="@string/title_activity_settings" >
        </activity>
        <receiver
            android:name="di.k23b.hw3.receivers.TriggerMonitoringBootReceiver"
            android:enabled="false" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="di.k23b.hw3.receivers.BatteryMonitoringReceiver"
            android:enabled="false"/>
    </application>
</manifest>

Relevant parts from the receiver (WIP !) :

private static void enable(Context context, boolean enable, String className) {
    PackageManager pacman = context.getPackageManager();
    final ComponentName componentName = new ComponentName(context, className);
    final int state = (enable) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
    pacman.setComponentEnabledSetting(componentName, state,  // line 81
            PackageManager.DONT_KILL_APP);
}

public static void enable(Context baseContext, boolean enable) {
    enable(baseContext, enable,                 // line 86
            TriggerMonitoringBootReceiver.class.getSimpleName());
}

And in SettingsActivity:

@Override
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
    if (MASTER_ENABLE.equals(key)) {
        TriggerMonitoringBootReceiver.enable(getBaseContext(),        // line 192
                sp.getBoolean(key, false));
        Toast.makeText(getApplicationContext(),
                "CB: " + sp.getBoolean(key, false), Toast.LENGTH_SHORT)
                .show();
    }
}



EDIT : all clear now, using ComponentName(Context pkg, Class<?> cls)- as for the difference in the APIs:

Calls to PackageManager.setComponentEnabledSetting will now throw an IllegalArgumentException if the given component class name does not exist in the application's manifest. - from the Android documentation

JJD
  • 50,076
  • 60
  • 203
  • 339
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361

4 Answers4

1
TriggerMonitoringBootReceiver.class.getSimpleName();

and package

PackageManager pacman = context.getPackageManager();

which together give

di.k23b.hw3.TriggerMonitoringBootReceiver

so you are missing "/receivers/" folder prefix in class name

Alex
  • 688
  • 6
  • 8
  • I get the context with `getBaseContext()` - tried with `getApplicationContext()` also to no avail - so my question is now : which `ComponentName()` [constructor](http://developer.android.com/reference/android/content/ComponentName.html#ComponentName%28android.content.Context,%20java.lang.String%29) should I use ? How should I get the context if using the constructor I _did_ use ? And why API 17 crashes while API 8 not ? – Mr_and_Mrs_D Mar 25 '13 at 18:11
1

Just summarizing information already in this thread.

Use the constructor ComponentName(Context pkg, Class<?> cls).

Also, the component name needs to be specified in the manifest. See JELLYBEAN in this link.
Calls to PackageManager.setComponentEnabledSetting will now throw an IllegalArgumentException if the given component class name does not exist in the application's manifest.

ben_joseph
  • 1,660
  • 1
  • 19
  • 24
  • Do I need to provide the complete class path for component in the Manifest? I have specified . in the manifest yet getting IllegalArgumentException. – Ishaan Apr 24 '17 at 13:54
  • @Ishaan "android:name=" should be the complete path I believe. I referred my code, and that's what I'm using. – ben_joseph Apr 24 '17 at 13:56
0

If you use AndroidAnnotations, use overridden class name instead.

// CORRECT class definition.
ComponentName receiver = new ComponentName(context, NotificationPublisher_.class);

but,

// THIS WILL GIVE YOU CRASH.
ComponentName receiver = new ComponentName(context, NotificationPublisher.class); 
Youngjae
  • 24,352
  • 18
  • 113
  • 198
0

Actually, it may have worked but a piece of advice: make sure your reciever is not disabled bro.

See, in you manifest it written as enabled="false", maybe, later day, it will cause you error.

NSV.
  • 65
  • 10