0

I have created a widget which has a clickable part which opens an activity showing all details instead of just one detail. But something odd happens.

Let me explain; the widget works perfectly, but when you create a widget, the button is not responding. So, when you create another widget, you will have 2 in total. Now, the button kind of works... it responds to my click but it crashes. If I completely reboot my phone and then use the button on the widget, it succesfully opens?

Here's my onUpdate():

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    for (int appWidgetId : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId);

        Intent statsIntent = new Intent(context, DetailsActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("name", WidgetConfigureActivity.loadTitle(context, appWidgetId));
        bundle.putString("id", WidgetConfigureActivity.Id(context, appWidgetId));
        bundle.putString("avatarurl", WidgetConfigureActivity.loadAvatar(context, appWidgetId));
        statsIntent.putExtras(bundle);

        PendingIntent statsPendingIntent = PendingIntent.getActivity(context, appWidgetId, statsIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);

        views.setOnClickPendingIntent(R.id.openInAppButton, statsPendingIntent);

        ComponentName componentName = new ComponentName(context.getPackageName(), WidgetProvider.class.getName());

        appWidgetManager.updateAppWidget(componentName, views);
    }
}

This is the NullpointerException users are receiving:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: it.bjarn.android.myapp, PID: 2764
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{it.bjarn.android.myapp/it.bjarn.android.myapp.activities.DetailsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(java.lang.String)' on a null object reference
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                      at android.app.ActivityThread.-wrap12(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6119)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(java.lang.String)' on a null object reference
                      at it.bjarn.android.myapp.activities.DetailsActivity.onCreate(DetailsActivity.java:111)
                      at android.app.Activity.performCreate(Activity.java:6679)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
                      at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6119) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

Also, helpful to know: When it works, it only opens the activity with the variables from 1 widget, instead of the widget you clicked on. It always opens the same one.

// Edit:

Added the onCreate() class by request. Nothing wrong with this one, since it works when opening the DetailsActivity by clicking on a button in another activity, it's only having issues with the widget.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
        Methods.setLanguage(this, preferences.getString("app_language", Locale.getDefault().getLanguage()));
        setContentView(R.layout.activity_details);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        window = getWindow();

        mContext = this;
        mApplication = getApplication();

        int mIntervalMultiply = Integer.parseInt(preferences.getString("app_sync_frequency", "5"));
        mInterval = 1000 * mIntervalMultiply;

        Bundle bundle = getIntent().getExtras();
        CharSequence title = bundle.getString("name");
        CharSequence id = bundle.getString("id");
        String avatar = bundle.getString("avatarurl");

        mChannelTitle = title != null ? title.toString() : null;
        mChannelId = id != null ? id.toString() : null;
        if (avatar != null) mChannelAvatar = avatar;

        if (mChannelTitle.isEmpty() || mChannelId.isEmpty()) {
            Intent search = new Intent(this, DetailsActivity.class);
            startActivity(search);
            Toast.makeText(this, R.string.error_connection_incorrect_response, Toast.LENGTH_LONG).show();
        }
        this.setTitle(title);

        mDbHelper = new DBHelper(this);

        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        mDescriptionView = (TextView) findViewById(R.id.descriptionContent);
        mCountOldView = (TextView) findViewById(R.id.oldCount);
        mTotalViewsView = (TextView) findViewById(R.id.viewsCount);
        mAvatarView = (ImageView) findViewById(R.id.avatarView);
        mBannerView = (ImageView) findViewById(R.id.banner);
        mCountView = (TickerView) findViewById(R.id.count);


        mHandler = new Handler();

        getInitialData(this);

        final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        if (mDbHelper.isInFavorites(mChannelId)) {
            fab.setImageResource(R.drawable.ic_star_amber_a400_24dp);
        } else {
            fab.setImageResource(R.drawable.ic_star_grey_400_24dp);
        }
    }
Bjarn Bronsveld
  • 989
  • 8
  • 18
  • You need to share your onCreate function please. – greysqrl Jan 21 '17 at 15:43
  • for the DetailsActivity.class? greysqrl – Bjarn Bronsveld Jan 21 '17 at 15:45
  • Yes please Bjarn. – greysqrl Jan 21 '17 at 15:46
  • Done! @greysqrl – Bjarn Bronsveld Jan 21 '17 at 15:58
  • According to your log file....the issue is that you are calling getString on a null object reference in onCreate. I suspect that at the point of your crash, preferences is null. Is that line 111 in your code? Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(java.lang.String)' on a null object reference at it.bjarn.android.myapp.activities.DetailsActivity.onCreate(DetailsActivity.java:111) – greysqrl Jan 21 '17 at 15:59
  • Separate the calls out and check if preferences is. I'll prior to calling 'getString', put a log in an else statement and that will validate the answer. – greysqrl Jan 21 '17 at 16:03
  • See comments below which explain more info about this. – Bjarn Bronsveld Jan 23 '17 at 20:18
  • Hi Bjarn, I saw but, if your log files are detailing an error as I pointed out.. then you need to address that error. It details a crash at a specific line, you need to look at that. – greysqrl Jan 25 '17 at 08:09

2 Answers2

0

According to your log file....the issue is that you are calling getString on a null object reference in onCreate. I suspect that at the point of your crash, preferences is null. Is that line 111 in your code? Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(java.lang.String)' on a null object reference at it.bjarn.android.myapp.activities.DetailsActivity.onCreate(D‌​etailsActivity.java:‌​111). Separate the calls out and check if preferences is. I'll prior to calling 'getString', put a log in an else statement and that will validate the answer. Ensure your context is valid when calling getSharedPreferences. (Sorry about the poor formatting, I'm answering on a mobile phone!)

greysqrl
  • 937
  • 3
  • 13
  • 31
0

Activity's getIntent() will return the Intent that had created the activity. If the activity is already created when you press the widget, you'll get the original Intent that created the activity. It might have the extras from previous widget clicked, or not at all.

You should separate activity creation from intent handling. See Activity.onNewIntent() callback.

(What's crashing your app is probably

CharSequence title = bundle.getString("name");

when bundle is null in the cases described above)

Yoni Gross
  • 816
  • 8
  • 16
  • I have fixed the issue which caused the same intent to open all the time, but it still keeps crashing. But when I force stop the app, then it works. – Bjarn Bronsveld Jan 22 '17 at 22:49
  • Of-course it works when you force stop the app, because then the activity is destroyed and your intent is creating a new activity. Otherwise, `Activity.getIntent()` will return an older intent (which has led to activity creation in the past) – Yoni Gross Jan 22 '17 at 23:43
  • No I mean, when I first create 1 widget; it isn't responding to my click. When I create a second widget; it responds, but crashes. When I NOW force close the app, it works perfectly. I fixed the intent issue which was opening the same one once it works by adding this line: `intent.setData(Uri.parse("tel:/"+ (int)System.currentTimeMillis()));` – Bjarn Bronsveld Jan 22 '17 at 23:53
  • I might not have made my answer clear enough, but a short search led me to the [this SO answer](http://stackoverflow.com/a/6357330/3942452). Not sure about why the widget is not responding to your clicks, but this is the explanation to the crash. – Yoni Gross Jan 23 '17 at 00:01
  • I think your 'not responding' error might be related to using the wrong updateAppWidget method. Try the `void updateAppWidget (int appWidgetId, RemoteViews views)` version – Yoni Gross Jan 23 '17 at 00:18
  • Nope that isn't the answer sadly.. It is very weird; the Bundle etc work perfectly after the force close. But before that, when having only 1 widget; it is not responding to clicks, and with 2 widgets the second one crashes, first one ain't responding either. – Bjarn Bronsveld Jan 23 '17 at 00:23