I have a Service that I start inside an Activity, but everytime the Service tries send the Broadcast back to the Activity I get this error:
07-22 17:14:21.890: E/AndroidRuntime(22445):
java.lang.RuntimeException: Error receiving broadcast Intent {
act=com.test.test.countDown flg=0x10 (has extras) } in
com.test.test.CookingTimer$1#1de35657 07-22 17:14:21.890:
E/AndroidRuntime(22445): at
android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:880)
07-22 17:14:21.890: E/AndroidRuntime(22445): at
android.os.Handler.handleCallback(Handler.java:739)
This is how I call the service:
timerIntent = new Intent(CookingTimer.this, TimerService.class);
startService(timerIntent);
registerReceiver(broadcastReceiver, new IntentFilter(TimerService.BROADCAST_ACTION));
This is my broadcast receiver:
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
And finally this is my Service class:
public class TimerService extends Service {
private Intent intent;
public static final String BROADCAST_ACTION = "com.test.test.countDown";
private Handler handler = new Handler();
private long initial_time;
long timeInMilliseconds = 0L;
#Override
public void onCreate() {
super.onCreate();
initial_time = SystemClock.uptimeMillis();
intent = new Intent(BROADCAST_ACTION);
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 1000); // 1 seconds
}
};
private void DisplayLoggingInfo() {
timeInMilliseconds = SystemClock.uptimeMillis() - initial_time;
int timer = (int) timeInMilliseconds / 1000;
intent.putExtra("time", timer);
sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Can someone explain me why I get that error and how can I possibly fix it? Maybe i'm missing some declaration inside my Manifest?
Related
I am making an android app that can send notifications even if the app is closed. So I added a NotificationService to call when the app is destroyed. But I get an error: System services not available to Activities before onCreate() when I force the app to stop.
This is the MainActivity.java:
public class MainActivity extends AppCompatActivity {
private Button button1;
private Button button2;
private Button button3;
private Button button4;
private static final String CHANNEL_ID = "telus";
private static final String CHANNEL_NAME = "telus app";
private static final String CHANNEL_DESC = "telus app notification";
private int count = 1;
Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1=(Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openActivity_web();
}
});
button2=(Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openActivationPage();
}
});
button3=(Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openMysql();
}
});
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(CHANNEL_DESC);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
displayNotification();
}
});
class sendnotif extends TimerTask {
public void run() {
displayNotification();
}
}
Timer timer = new Timer();
timer.schedule(new sendnotif(), 0, 5000);
}
public void displayNotification(){
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_alarm)
.setContentTitle("Titre de la notification")
.setContentText("C'est le text de la notification")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
;
NotificationManagerCompat mNotifMgr = NotificationManagerCompat.from(this);
mNotifMgr.notify( 1, mBuilder.build());
}
public void openActivity_web(){
Intent intent = new Intent(this, WebPage.class);
startActivity(intent);
}
public void openActivationPage(){
Intent intent = new Intent(this, ActivationPage.class);
startActivity(intent);
}
public void openMysql(){
Intent intent = new Intent(this, mysql_display.class);
startActivity(intent);
}
protected void onDestroy(){
super.onDestroy();
startService(new Intent(this, NotificationService.class));
}
}
and this is the NotificationService.java:
public class NotificationService extends Service {
Timer timer;
TimerTask timerTask;
String TAG = "Timers";
int Your_X_SECS = 5;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
}
#Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
stoptimertask();
super.onDestroy();
}
//we are going to use a handler to be able to run in our TimerTask
final Handler handler = new Handler();
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, after the first 5000ms the TimerTask will run every 10000ms
timer.schedule(timerTask, 5000, Your_X_SECS * 1000); //
//timer.schedule(timerTask, 5000,1000); //
}
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
MainActivity notif = new MainActivity();
notif.displayNotification();
}
});
}
};
}
}
This is the error log when I try to manually stop the app:
2019 - 07 - 16 20: 10: 23.079 23334 - 23334 / com.example.testapp E / AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.testapp, PID: 23334
java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.Activity.getSystemService(Activity.java: 5581)
at androidx.core.app.NotificationManagerCompat. < init > (NotificationManagerCompat.java: 158)
at androidx.core.app.NotificationManagerCompat.from(NotificationManagerCompat.java: 153)
at com.example.testapp.MainActivity.displayNotification(MainActivity.java: 103)
at com.example.testapp.NotificationService$1$1.run(NotificationService.java: 89)
at android.os.Handler.handleCallback(Handler.java: 751)
at android.os.Handler.dispatchMessage(Handler.java: 95)
at android.os.Looper.loop(Looper.java: 154)
at android.app.ActivityThread.main(ActivityThread.java: 6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 756)
Thank you for your help.
I need to create a service that allow my application to work also when I close it, I’ve tried with STICKY_SERVICE but it doesn’t work... if anyone can decribe me how I can do this please answer this question.
It works with android 7.1 and it doesn’t with other versions
Here is my code...
public class SensorService extends Service {
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
stoptimertask();
Intent broadcastIntent = new Intent("RestartSensor");
sendBroadcast(broadcastIntent);
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.i("in timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
This is my service Restarter...
public class SensorRestarterBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops");
context.startService(new Intent(context, SensorService.class));
}
}
And the mainClass
public class MainActivity extends AppCompatActivity {
Intent mServiceIntent;
private SensorService mSensorService;
Context ctx;
public Context getCtx() {
return ctx;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
setContentView(R.layout.activity_main);
mSensorService = new SensorService(getCtx());
mServiceIntent = new Intent(getCtx(), mSensorService.getClass());
if (!isMyServiceRunning(mSensorService.getClass())) {
startService(mServiceIntent);
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("isMyServiceRunning?", true+"");
return true;
}
}
Log.i ("isMyServiceRunning?", false+"");
return false;
}
#Override
protected void onDestroy() {
stopService(mServiceIntent);
Log.i("MAINACT", "onDestroy!");
super.onDestroy();
}
}
This restartthe service correctly but after 3/4 seconds it die.
I've added this to my manifest
<service
android:name=".SensorService"
android:enabled="true" >
</service>
<receiver
android:name=".SensorRestarterBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped">
<intent-filter>
<action android:name="RestartSensor"/>
</intent-filter>
</receiver>
Add the following code to your sensor service and edit as per your need. You need to bind the sticky service to a notification to keep the service alive and start in the foreground.
#Override
public void onCreate() {
super.onCreate();
Intent notifIntent = new Intent(this, SensorService.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, notifIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.smslogo_100x100)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setContentTitle(getResources().getString(R.string.app_name))
.setContentText("Running")
.setContentIntent(pi)
.build();
startForeground(101010, notification);
}
This will rectify the issue you are facing and the service will run forever.
Please guide me in this. Appreciate all your help.
My background service is toasting ABC
//-------------------String displayingText = "ABC";-----------------
And I have two strings, ABC and DEF declared in mainactivity.java
How do I pass the value displayingText from main activity to this service.
How do I change the displayingText to DEF after the toast ABC finished.
MyService.Java
public class MyService extends Service {
public static final long INTERVAL=3000;//variable to execute services every 5 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
//the get intent dont work. where or how should i put it?
Intent myIntent = getIntent();
if (myIntent !=null && myIntent.getExtras()!=null)
String value = myIntent.getExtras().getString(PassToService);
#Nullable
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("unsupported Operation");
}
#Override
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
#Override
public void onTaskRemoved(Intent rootIntent) {
stopSelf();///its will stop service
super.onTaskRemoved(rootIntent);
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
super.onDestroy();
}
//inner class of TimeDisplayTimerTask
private class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast at every 10 second
//String displayingText = "ABC";
String displayingText = myIntent.getStringExtra("PassToService");
final Toast Notify = Toast.makeText(getApplicationContext(), displayingText, Toast.LENGTH_SHORT);
Notify.setGravity(Gravity.CENTER, 0, 0);
Notify.show();
Handler cancelToast = new Handler();
cancelToast.postDelayed(new Runnable() {
#Override
public void run() {
Notify.cancel();
}
}, 1000);
}
});
}
}
}
You can do it by passing value from activity to service-
startService(new Intent(YourActivity.Service.class).putExtra("key","value"));
As soon as my application starts I get a crash and I can't figure out why. I have a Service that is used as a timer to count the number of seconds since the timer started, this then gets passed back to my MainActivity.
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "BroadcastTest";
private Intent intent;
private Chronometer timer;
private Button start;
private Button stop;
private EditText hourlyRate;
private TextView money;
private long timeWhenStopped = 0;
private double moneyEarned;
private double secondsRate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timer = (Chronometer) findViewById(R.id.chronometer);
start = (Button) findViewById(R.id.start);
stop = (Button) findViewById(R.id.stop);
hourlyRate = (EditText) findViewById(R.id.hourlyRate);
money = (TextView) findViewById(R.id.money);
intent = new Intent(this, Timer.class);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startService(new Intent(MainActivity.this, Timer.class));
timer.setBase(SystemClock.elapsedRealtime() + timeWhenStopped);
timer.start();
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timeWhenStopped = timer.getBase() - SystemClock.elapsedRealtime();
timer.stop();
}
});
timer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener()
{
#Override
public void onChronometerTick(Chronometer chronometer){
long timeElapsed = SystemClock.elapsedRealtime() - timer.getBase();
int seconds = (int) timeElapsed / 1000;
double hrlyRate = Double.parseDouble(hourlyRate.getText().toString());
secondsRate = (hrlyRate / 60) / 60;
moneyEarned = secondsRate * seconds;
double displayMoney = Math.round(moneyEarned * 100.0)/100.0;
Log.d("hours",Long.toString(seconds));
money.setText("$"+Double.toString(displayMoney));
}
});
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
#Override
public void onResume() {
super.onResume();
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(Timer.BROADCAST_ACTION));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
stopService(intent);
}
private void updateUI(Intent intent) {
String counter = intent.getStringExtra("counter");
Log.d("SERVICE_SECONDS", counter);
}
}
Timer.java:
public class Timer extends Service {
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "b.calvin.com.dirtymoney";
private final Handler handler = new Handler();
Intent intent;
int counter = 0;
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
countSeconds();
handler.postDelayed(this, 1000); // 1 second
}
};
#Override
public void onCreate()
{
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 0); // 1 second
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void countSeconds() {
Log.d(TAG, Integer.toString(++counter));
sendBroadcast(intent);
}
}
Error:
FATAL EXCEPTION: main
Process: b.calvin.com.dirtymoney, PID: 3348
java.lang.RuntimeException: Error receiving broadcast Intent { act=b.calvin.com.dirtymoney flg=0x10 } in b.calvin.com.dirtymoney.MainActivity$4#bf337ff
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:891)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:139)
at b.calvin.com.dirtymoney.MainActivity.updateUI(MainActivity.java:113)
at b.calvin.com.dirtymoney.MainActivity.access$600(MainActivity.java:20)
at b.calvin.com.dirtymoney.MainActivity$4.onReceive(MainActivity.java:93)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Seems like you forgot to put your counter variable into the Intent, so you're passing null to Log.d() as the message, resulting in a NullPointerException.
Something like this should work:
private void countSeconds() {
Log.d(TAG, Integer.toString(++counter));
Intent counterIntent = new Intent(BROADCAST_ACTION);
counterIntent.putExtra("counter", counter);
sendBroadcast(counterIntent);
}
Also, counter is an int, so you should call getIntExtra() instead of getStringExtra():
private void updateUI(Intent intent) {
int counter = intent.getIntExtra("counter");
Log.d("SERVICE_SECONDS", Integer.toString(counter));
}
i am doing an application that will notify the user after 2 weeks. but i set the timer in 2 mins so i could test if my application will notify the user. my problem is when i turn on the notification and close my app. i will get an error in 2 minutes no notification but when my app is running the notification is working fine. In the logcat my error is in Bundle showData = i.getExtras(); i think the problem is when i closed my app, the Bundle passData is getting null?
PhoneInformation.java
case R.id.bTurnOn:
Bundle passData = new Bundle();
Intent intent = new Intent(PhoneInformation.this,NotificationService.class);
passData.putInt("keyid", rowId);
intent.putExtras(passData);
startService(intent);
break;
NotificationService.java
public class NotificationService extends Service{
int rowId;
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Toast.makeText(this, "OnCreate()", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "OnDestroy()", Toast.LENGTH_SHORT).show();
}
#Override
#Deprecated
public void onStart(final Intent i, int startId) {
// TODO Auto-generated method stub
super.onStart(i, startId);
final Handler handler = new Handler();
Timer timer;
TimerTask timertask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#SuppressWarnings("deprecation")
public void run() {
Bundle showData = i.getExtras();
rowId = showData.getInt("keyid");
Bundle passData = new Bundle();
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(NotificationService.this,SMSPhoneMessage.class);
passData.putInt("keyid", rowId);
notificationIntent.putExtras(passData);
PendingIntent pendingIntent = PendingIntent.getActivity(NotificationService.this, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification = new Notification(R.drawable.ic_launcher, "New Message", System.currentTimeMillis());
notification.setLatestEventInfo(NotificationService.this, "New Message", "Please come to me immediately", pendingIntent);
nm.notify(123, notification);
}
});
}
};
timer = new Timer();
timer.schedule(timertask, 10000);
}
}