I have a button on my activity that starts a notification and then also starts a Countdown Timer with an Async Task. The purpose of the code is to convert the millisUntilFinished to readable time and send it to my GUI in the second activityI get this fatal exception:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.idkbro.pashchallenge, PID: 25702
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:318)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.os.CountDownTimer$1.<init>(CountDownTimer.java:114)
at android.os.CountDownTimer.<init>(CountDownTimer.java:114)
at com.idkbro.pashchallenge.MainActivity$1CDTTask$1.<init>(MainActivity.java:0)
at com.idkbro.pashchallenge.MainActivity$1CDTTask.doInBackground(MainActivity.java:250)
at com.idkbro.pashchallenge.MainActivity$1CDTTask.doInBackground(MainActivity.java:196)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Here they said the error could be because of trying to update the GUI in the asynctask, but this isnt in my case because í send variable to the activity using an intent service. I think the problem could be how i "set up" my asynctask
The MainActivity class when the accept button is(P.S: so sorry about the code if its a but messy :( ):
public void agreeButton (View v){
Intent intent = new Intent(MainActivity.this, CountdownPage.class);
startActivity(intent);
NotificationCompat.Builder notificationBuiler = new NotificationCompat.Builder(this)
.setContentTitle("Pash Challenge")
.setContentText("You have so many minutes left")//TODO make notification display countdown
.setTicker("Alert new message")
.setSmallIcon(R.drawable.pashicon);//Code to display notification
Intent moreInfoIntent = new Intent(MainActivity.this, MoreInfoNotification.class);
notificationManager =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationID,notificationBuiler.build());
// Used to stack tasks across activites so we go to the proper place when back is clicked
TaskStackBuilder tStackBuilder = TaskStackBuilder.create(this);
// Add all parents of this activity to the stack
tStackBuilder.addParentStack(MoreInfoNotification.class);
// Add our new Intent to the stack
tStackBuilder.addNextIntent(moreInfoIntent);
// Define an Intent and an action to perform with it by another application
// FLAG_UPDATE_CURRENT : If the intent exists keep it but update it if needed
PendingIntent pendingIntent = tStackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
// Defines the Intent to fire when the notification is clicked
notificationBuiler.setContentIntent(pendingIntent);
isNotificationActive =true;
class CDTTask extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
Calendar calendar = Calendar.getInstance();
Long preTime = calendar.getTimeInMillis();
calendar.add(Calendar.DATE, 2);// set milliseconds for 2 days
Long postTime = calendar.getTimeInMillis();
Long delay = postTime - preTime;
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC_WAKEUP, postTime, null);
CountDownTimer timer = new CountDownTimer(delay, 1) {
@Override
public void onTick(final long millisUntilFinished) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//SendAndCovert milliseconds to CoundownPage
SAndCDays(millisUntilFinished);
SAndCHours(millisUntilFinished);
SAndCMinutes(millisUntilFinished);
SAndCSeconds(millisUntilFinished);
}//End run
});//End runOnUiThread
}//End onTick
@Override
public void onFinish() {
}//End OnFinish
void SAndCDays(Long milli){ //Code to convert milliseconds to days and send it to CountdownPage.java
Long millis = (milli / (1000*60*60*24));
String days = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("days", days);
startActivity(numIntent);
}//End SAndCDays
void SAndCMinutes(Long milli){ //Code to convert milliseconds to minutes and send it to CountdownPage.java
long millis = ((milli / (1000 * 60)) % 60);
String minutes = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("minutes", minutes);
startActivity(numIntent);
}//End SAndCMinutes
//Code to convert milliseconds to hours and send it to CountdownPage.java
void SAndCHours(Long milli){
long millis = (milli/ (1000 * 60 * 60)) % 24;
String hours = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("hours", hours);
startActivity(numIntent);
}//End SAndCHours
//Code to convert milliseconds to seconds and send it to CountdownPage.java
void SAndCSeconds(Long milli){
long millis = (milli/ 1000) % 60;
String seconds = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("seconds", seconds);
startActivity(numIntent);
} //End SAndCSeconds
};
timer.start();
return null;
}//End doInBackground
}
CDTTask object = new CDTTask();
object.execute();//Code to start Countdown Async task
} // End agreeButton
Here is my Alert Receiver class if its of any help:
public class AlertReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
createNotification(context, "Times Up", " x Seconds has past","alert");// TODO change to CDT Time
}//End onReceive
public void createNotification(Context context, String msg,
String txtMsg,String msgAlert) {
PendingIntent notificIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
// Builds a notification
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.pashicon)
.setContentTitle(msg)
.setTicker(msgAlert)
.setContentText(txtMsg);
mBuilder.setContentIntent(notificIntent);
mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
}//End createNotification
}//End AlertReceiver.class
And how i receive and display the coveted times from the service:
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_challenge_page);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
TextView txtTimerDay=(TextView)findViewById(R.id.txtTimerDay);
TextView txtTimerMinute=(TextView)findViewById(R.id.txtTimerMinute);
TextView txtTimerHour=(TextView)findViewById(R.id.txtTimerHour);
TextView txtTimerSecond=(TextView)findViewById(R.id.txtTimerSecond);
txtTimerDay.setText(getIntent().getStringExtra("days"));
txtTimerMinute.setText(getIntent().getStringExtra("minutes"));
txtTimerHour.setText(getIntent().getStringExtra("hours"));
txtTimerSecond.setText(getIntent().getStringExtra("seconds"));
}