Not Able to modify an Activity from my Broadcast Receiver of Alarm Manager

54 Views Asked by At

I want to modify my plan which is an app database everyday at midnight. Also I want to modify my Activity which showing certain numbers that are supposed to change daily according to the plan information. I am able using the Alarm Manager to update the database but I am unable to change the textviews of the Activity. It is giving me this error: java.lang.ClassCastException: android.app.ReceiverRestrictedContext cannot be cast to com.example.bleh.myapplication.feature2

Here is my Alarm Receiver Class:

package com.example.bleh.myapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.example.bleh.myapplication.DB.AppDatabase;
import com.example.bleh.myapplication.DB.Plan;
import com.example.bleh.myapplication.DB.User;
import com.example.bleh.myapplication.Utils1.FormulaUtils;
import com.github.lzyzsd.circleprogress.DonutProgress;

public class AlarmReceiver extends BroadcastReceiver {

    private static final String DEBUG_TAG = "AlarmReceiver";
    public AppDatabase mydb;
    Plan plan;

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Alarm worked.", Toast.LENGTH_LONG).show();
        mydb = AppDatabase.getInstance(context);
        final long planid = intent.getExtras().getLong("planid");
        final long userid = intent.getExtras().getLong("uid");
        final String requirements = intent.getExtras().getString("requirements");
        Log.wtf("PlanId: ",planid+"");
        Log.wtf("UserId: ",userid+"");
        Log.wtf("Requirements",requirements);
        plan = mydb.getPlanDao(context).getPlanById((int) planid);
        final User user = mydb.getUserDao(context).getUserById((int) userid);
        plan.setCurrentWeight(FormulaUtils.reCalculateWeight(plan.getCurrentWeight(), Double.parseDouble(requirements)));
        plan.setBmr(Double.parseDouble(FormulaUtils.calculateBmr(user.getSex(), plan.getCurrentWeight(), user.getHeight(), user.getBirthDay())));
        plan.setNbOfDays(plan.getNbOfDays() - 1);
        mydb.getPlanDao(context).update(plan);
        TextView requirement = ((feature2)context).findViewById(R.id.requirements);
        TextView Days = ((feature2)context).findViewById(R.id.days);
        DonutProgress DailyProgress = ((feature2)context).findViewById(R.id.donut_progress);
        requirement.setText(FormulaUtils.CalulcateDailyRequirements(plan.getWorkoutPerWeek(), plan.getBmr()));
        Days.setText(plan.getNbOfDays()+"");
        int progress = 0;
        DailyProgress.setProgress((float) progress);
//        Intent newIntent = new Intent(context, feature2.class);
//        newIntent.putExtra("uid", userid);
//        newIntent.putExtra("planid", planid);
//        context.startActivity(newIntent);
    }

}

Here is my Feature Activity(part of it):

public class feature2 extends AppCompatActivity {

    public AppDatabase mydb;
    TextView BMR,requirements,days;
    Button addfood,addex,nextday;
    LinearLayout mainLayout;
    Button Meas,Bluetooth;
    DonutProgress donutProgress;
    Plan plan;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_feature2);
        Intent intent = getIntent();
        requirements = findViewById(R.id.requirements);
        donutProgress = findViewById(R.id.donut_progress);
        days = findViewById(R.id.days);
        final long planid = intent.getExtras().getLong("planid");
        final long userid = intent.getExtras().getLong("uid");
        mydb = AppDatabase.getInstance(feature2.this);
        plan = mydb.getPlanDao(feature2.this).getPlanById((int) planid);
        requirements.setText(FormulaUtils.CalulcateDailyRequirements(plan.getWorkoutPerWeek(), plan.getBmr()));
        Intent intent1 = new Intent(this, AlarmReceiver.class);
        intent1.putExtra("uid", userid);
        intent1.putExtra("planid", planid);
        intent1.putExtra("requirements",requirements.getText().toString());
        Calendar updateTime = Calendar.getInstance();
        updateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
        updateTime.set(Calendar.HOUR_OF_DAY, 20);
        updateTime.set(Calendar.MINUTE, 03);
        updateTime.set(Calendar.SECOND,0);
        Date milliseconds = updateTime.getTime();
        Log.wtf("millisec",milliseconds+"");
        long millis = milliseconds.getTime();
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
                intent1, PendingIntent.FLAG_ONE_SHOT);

        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, millis , pendingIntent);
        Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
   }
}
1

There are 1 best solutions below

3
Son Truong On BEST ANSWER

This line make your app crash

TextView requirement = ((feature2)context).findViewById(R.id.requirements);

context is an instance of ReceiverRestrictedContext, feature2 is an instance of AppCompatActivity whose parent is ContextThemeWrapper. feature2 is not an instance of ReceiverRestrictedContext, that why your app throws an ClassCastException and make your app crash.

Solution: There are many ways to solve your problem, here is a simple one.

Step 1: In AlarmReceiver class, start feature2 activity with FLAG_ACTIVITY_SINGLE_TOP | FLAG_ACTIVITY_CLEAR_TOP.

public class AlarmReceiver extends BroadcastReceiver {

    private static final String DEBUG_TAG = "AlarmReceiver";
    public AppDatabase mydb;
    Plan plan;

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Alarm worked.", Toast.LENGTH_LONG).show();
        mydb = AppDatabase.getInstance(context);
        final long planid = intent.getExtras().getLong("planid");
        final long userid = intent.getExtras().getLong("uid");
        final String requirements = intent.getExtras().getString("requirements");
        Log.wtf("PlanId: ",planid+"");
        Log.wtf("UserId: ",userid+"");
        Log.wtf("Requirements",requirements);
        plan = mydb.getPlanDao(context).getPlanById((int) planid);
        final User user = mydb.getUserDao(context).getUserById((int) userid);
        plan.setCurrentWeight(FormulaUtils.reCalculateWeight(plan.getCurrentWeight(), Double.parseDouble(requirements)));
        plan.setBmr(Double.parseDouble(FormulaUtils.calculateBmr(user.getSex(), plan.getCurrentWeight(), user.getHeight(), user.getBirthDay())));
        plan.setNbOfDays(plan.getNbOfDays() - 1);
        mydb.getPlanDao(context).update(plan);

        // Calculate all data before sending to feature2 activity
        String requirement = FormulaUtils.CalulcateDailyRequirements(plan.getWorkoutPerWeek(), plan.getBmr());
        String day = plan.getNbOfDays() + "";
        float progress = 0F;

        // Start feature2 activity with updated data
        Intent updateFeature2Intent = new Intent(context, feature2.class);
        updateFeature2Intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); // Add this flag
        newIntent.putExtra("requirement", requirement);
        newIntent.putExtra("day", day);
        newIntent.putExtra("progress", progress);
        context.startActivity(newIntent);
    }
}

Step 2: If feature2 activity is on backstack and visible to user, onNewIntent will get called, in that case get the data and update your UI there.

public class feature2 extends AppCompatActivity {

    ...

    // Add this method
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        // Get data from intent
        String requirement = intent.getStringExtra("requirement");
        String day = intent.getStringExtra("day");
        float progress = intent.getFloatExtra("progress", 0F);

        // Update UI
        TextView requirements = findViewById(R.id.requirements);
        TextView Days = findViewById(R.id.days);
        DonutProgress dailyProgress = findViewById(R.id.donut_progress);

        requirements.setText(requirement);
        Days.setText(day);
        dailyProgress.setProgress(progress);
    }
}