I have an android application, which contains a main activity which displays information to the user.
When MainActivity starts, A service is created/started which checks a web service on every 10 seconds - if the Web service result will show in a notification.
I start the service from Main activity using Intent,
getActivity().startService(new Intent(getActivity(), NotificationService.class));
I Also try this code, (But same result).
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
getActivity().startService(new Intent(getActivity(), NotificationService.class));
}
});
If service started I get warning In my Logcat,
Skipped 91 frames! The application may be doing too much work on its main thread.
My notification service code,
public class NotificationService extends Service {
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
long current_times;
String c_time;
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
static HttpClient client = new DefaultHttpClient();
private Timer mTimer = null;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD) #SuppressLint("NewApi") #Override
public void onCreate() {
// cancel if already existed
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
SharedPreferences.Editor editor = getSharedPreferences("notification_oldtime", MODE_PRIVATE).edit();
editor.putInt("old_trail_time", 0);
editor.putInt("old_sample_time", 0);
editor.putInt("old_neworder_time", 0);
editor.commit();
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
public long current_time_get(){
return current_times;
}
class TimeDisplayTimerTask extends TimerTask {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN) #Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// My webservice code for notification
}
}
}
Try using IntentService instead of Service. IntentService does its work on a separate thread.
serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder binder) {
try {
((NoteBinder) binder).service.startService(new Intent(
MyActivity.this, NotificationService.class));
MyLog.d(TAG, "onServiceConnected is called; "
+ className.getClassName());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName className) {
MyLog.d(TAG, "onServiceDisconnected is called; "
+ className.getClassName());
}
};
bindService(
new Intent(BaseActivity.this, NotificationService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
instead of using start service use bind service.
Related
I have a service works by pressing a button.
There's a counter that works every second inside it.
I tested it and it's working.
It also works after the application is shut down.
The problem after the application is closed
Then I'm doing a run
test the service it doesn't work.
How do I make it works after i do run from inside Android studio ?
//MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!isMyServiceRunning(SensorService.class)){
Log.i("isServiceRunning","Not");
}else {
Log.i("isServiceRunning","Don");
}
}
public void Test(View view){
startService(new Intent(this, SensorService.class));
}
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())) {
return true;
}
}
return false;
}
}
/// Service
public class SensorService extends Service {
public int counter=0;
public SensorService() {
super();
Log.i("HERE", "here I am!");
}
#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!");
// Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);
stoptimertask();
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
Log.i("startTimer", "Don");
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() {
Log.i("initializeTimerTask", "Don");
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;
}
}
If you use "Run" from Android Studio (regardless if it's tests or the app) the service will always stop first since the whole application will always stop first. The service will not stop if you start the App manually from the device.
There is no way around this and is actually a good feature. It ensures that the App is always started cleanly on every run. If you want to share the reason of why you want to do this, there might be an alternate way of solving your problem.
I'm using xiomi and vivo device and while removing app from recents in both the device service is being killed and not restarting as I had used receiver.
I had also used startForeground for OREO+ version but still its not working in xiomi and vivo phones. So I just want to create a service which just print log at every seconds and it should continue even if user remove it from recents.
Thank you in advance.
Till now I had tried this code shown below:
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_destroy", "ondestroy!");
Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
stoptimertask();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i("EXIT_taskRemoved", "ondestroy!");
Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
stoptimertask();
}
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;
}
}
Its not working in xiomi and vivo devices while removing it from recents
Services always run in main thread, you should implement your service in another Thread. Just use IntentService instead of Service.
I'm trying to stop my service with stopService(), but it will still running. It only stops when I unregister the brodcast receiver, but when I register that again, there will be two actions activated at the same time.
The thread is still running somehow, I really tried everything and reading every single post on the forum but I dind't find a solution.
Service Class
public class MyService extends Service {
final static String MY_ACTION = "MY_ACTION";
private static Context context;
private Timer timer;
public String Data;
String ok = "Database\n";
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
MyThread myThread = new MyThread();
myThread.start();
return super.onStartCommand(intent, flags, startId);
}
public class MyThread extends Thread{
#Override
public void run() {
// TODO Auto-generated method stub
try {
int delay = 1000; // delay for 1 sec.
int period = 5 * 1000; // repeat every 120 sec.
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Calendar c = Calendar.getInstance();
Data = String.valueOf((c.get(Calendar.MILLISECOND)));
Intent intent = new Intent();
intent.setAction(MY_ACTION);
intent.putExtra("DATAPASSED", ok);
sendBroadcast(intent);
}
}, delay, period);
} catch (Exception ex) {
ex.printStackTrace();
}
stopSelf();
}
}
}
MainActivity
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyService.MY_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
final Intent intent = new Intent(MainActivity.this, MyService.class);
//Start our own service
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//registerReceiver(broadcastReceiver, intentFilter);
startService(intent);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//unregisterReceiver(broadcastReceiver);
stopService(intent);
}
});
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
unregisterReceiver(broadcastReceiver);
super.onStop();
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int datapassed = intent.getIntExtra("DATAPASSED", 0);
String s = intent.getAction().toString();
String s1 = intent.getStringExtra("DATAPASSED");
textview.append(s1);
}
};
What I'm doing wrong is calling stopSelf() inside my Thread which is causing the service calling the onDestroy() method. I just removed that and added myTimer and myTask as local variables, then I could add myTimer.cancel() onDestroy and it worked.
i need to call a method after 2 minutes. i have tried handler and timer but when app close then it doesn't work. then i have call timer in service and start service on button click and stop service after 2 minutes. it works but problem is sometime service calls itself. below is my code.
MyService class
public class MyService extends Service {
private static Retrofit retrofit = null;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
new CountDownTimer(120000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d("message", "start");
}
public void onFinish() {
Log.d("message", "finish");
callMyMethod();
stopService(new Intent(MyService.this, MainActivity.class));
}
}.start();
}
MainActivity class from where i start service.
stopService(new Intent(getContext(), MyService.class));
startService(new Intent(getContext(), MyService.class));
Manifest
<service android:name="MyService" android:enabled="true" android:exported="true"/>
NOTE: I WANT TO CALL SERVICE ONLY ON BUTTON CLICK AND STOP SERVICE AFTER 2 MINUTES.
please need help to solve this issue or If there is other good solution other than services.
Updated: if network response in not success how can i handle to retry.
MyService class
public class MyService extends Service {
private static Retrofit retrofit = null;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
new CountDownTimer(120000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d("mess", "start");
}
public void onFinish() {
Log.d("mess", "finish");
selectDriverForJOb();
stopSelf();//(new Intent(MyService.this, MainActivity.class));
}
}.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
private void selectDriverForJOb() {
SharedPreferences sharedPreferences = getSharedPreferences("Login_credentials", MODE_PRIVATE);
String user_id = sharedPreferences.getString("userID", null);
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
APIServices_interface selectDriver_interface = retrofit.create(APIServices_interface.class);
Call<SelectDriverforJobResult> call = null;
try {
call = selectDriver_interface.selectDriverforJob(user_id);
} catch (Exception e) {
e.printStackTrace();
}
if (call != null) {
try {
call.enqueue(new Callback<SelectDriverforJobResult>() {
#Override
public void onResponse(Call<SelectDriverforJobResult> call, Response<SelectDriverforJobResult> response) {
SelectDriverforJobResult selectDriver = response.body();
String message = selectDriver.getMessage();
if(!(message.equalsIgnoreCase("success"))){
}
}
#Override
public void onFailure(Call<SelectDriverforJobResult> call, Throwable t) {
Log.d("mess : ", "Error Updating ");
//want to retry
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
override onStartCommand in service and return START_NOT_STICKY it will not restart the
public void onStartCommand()
{
return START_NOT_STICKY
}
and use stopSelf() insted of stopService(new Intent(getContext(), MyService.class));
Your Service will not run after app close, Read background restriction.
And this is not really a Service use case.
The solution can be to your problem is AlarmManager . Set an alarm for exact after 2 minutes and your Receiver willget called when its triggered . Before using AlarmManger give a read to setExactAndAllowWhileIdle() and setExact().
Alternatively you can also use WorkManager to set a Exact Job . But This will be an overkill if you do not need Job Constraints. So if your work does not depends of any Constraints like Network connection or other you can go with AlarmManger.
PS:- If your task depends on a Network connection then you should go with WorkManager. Read Schedule tasks with WorkManager .
I am trying to create a service that will show a toast every second with the most recent running application. Every time I start the service, I get a NullPointerException. What can I do to avoid this?
public class CheckRunningActivity extends Service {
private static final String TAG = "CheckRunningActivity";
boolean checkApps;
private Timer mTimer = null;
private Handler mHandler = new Handler();
private ActivityManager am;
public static final long NOTIFY_INTERVAL = 1000; // 1 second
#Override
public void onDestroy() {
mTimer.cancel();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Log.d(TAG, "I created it");
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
Log.d(TAG, "Its running");
String packageName = am.getRunningTasks(1).get(0).topActivity
.getPackageName();
Toast.makeText(getBaseContext(), packageName, Toast.LENGTH_LONG).show();
Log.d(TAG, "Make Toast");
}
});
}
}
}
you can't directly call toast from service . you need a handler for this. see answer here.
after looking at the code again, I realized that I had not properly initialized the Activity Manager.
Here is the corrected code...
public class CheckRunningActivity extends Service {
private static final String TAG = "CheckRunningActivity";
boolean checkApps;
private Timer mTimer = null;
private Handler mHandler = new Handler();
private ActivityManager am;
public static final long NOTIFY_INTERVAL = 1000; // 1 second
#Override
public void onDestroy() {
mTimer.cancel();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Log.d(TAG, "I created it");
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
Log.d(TAG, "Its running");
String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName();
Toast.makeText(getBaseContext(), packageName, Toast.LENGTH_LONG).show();
Log.d(TAG, "Make Toast");
}
});
}
}
}