androidxamarinxamarin.androidwear-osandroid-wear-2.0

Xamarin NPE on Confirmation Activity on Wear


I'm developing a Wear application and wanted to show a Confirmation message to the user after a click.

I know that for Wear dedicated tools like ConfirmationActivity exist, but after trying to show it I receive a Null Pointer Exception:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference

This is the offending code causing the NPE:

Intent intent = new Intent(ApplicationContext, typeof(ConfirmationActivity));
intent.PutExtra(ConfirmationActivity.ExtraAnimationType, ConfirmationActivity.SuccessAnimation);
StartActivity(intent);

Here's the application manifest (notice I declared ConfirmationActivity):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="xx.xxxxxxx.xxxxxxx" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="28" />
    <uses-feature android:name="android.hardware.type.watch" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
    <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@android:style/Theme.DeviceDefault">
        <uses-library android:name="com.google.android.wearable" android:required="true" />
        <!--
      Set to true if your app is Standalone, that is, it does not require the handheld
      app to run.
    -->
        <meta-data android:name="com.google.android.wearable.standalone" android:value="true" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="${applicationId}" />
            </intent-filter>
        </receiver>
        <receiver android:name=".BootReceiver" android:enabled="true" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
    <activity android:name="android.support.wearable.activity.ConfirmationActivity"></activity>
    </application>
</manifest>

This is the stack trace:

07-02 07:41:50.270 E/AndroidRuntime( 6760): java.lang.RuntimeException: Unable to start activity ComponentInfo{xx.xxxxxxxx.xxxxxx/android.support.wearable.activity.ConfirmationActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.ActivityThread.-wrap11(Unknown Source:0)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.os.Handler.dispatchMessage(Handler.java:105)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.os.Looper.loop(Looper.java:164)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.ActivityThread.main(ActivityThread.java:6541)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at java.lang.reflect.Method.invoke(Native Method)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
07-02 07:41:50.270 E/AndroidRuntime( 6760): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.support.wearable.view.ConfirmationOverlay.updateImageView(ConfirmationOverlay.java:302)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.support.wearable.view.ConfirmationOverlay.updateOverlayView(ConfirmationOverlay.java:249)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.support.wearable.view.ConfirmationOverlay.showOn(ConfirmationOverlay.java:194)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.support.wearable.activity.ConfirmationActivity.onCreate(ConfirmationActivity.java:79)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.Activity.performCreate(Activity.java:6975)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
07-02 07:41:50.270 E/AndroidRuntime( 6760):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)

Solution

  • I think your context is incorrect. Try this:

    Intent intent = new Intent (this, typeof(ConfirmationActivity))
        .SetFlags (ActivityFlags.NewTask | ActivityFlags.NoAnimation)
        .PutExtra (ConfirmationActivity.ExtraAnimationType, ConfirmationActivity.SuccessAnimation)
        .PutExtra (ConfirmationActivity.ExtraMessage, "Message Goes Here");
    StartActivity (intent);
    

    And if that doesn't work either, you might have to override the Intent handling function too, as you can see here and here.