I have a button on which following code is written
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(Formact.this, MyService.class);
MyService.pintent = PendingIntent.getService(Formact.this, 0, intent, 0);
MyService.alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
MyService.alarm.setRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), 5000, MyService.pintent);
now once the services is created it has to destroy on a specific action but after each time it destroy it starts again.
here is my service class
public class MyService extends Service {
public static int counter = 0;
public static PendingIntent pintent;
public static AlarmManager alarm;
Boolean save=false;
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return new Binder() ;
}
#Override
public void onCreate() {
Toast.makeText(this, "Service was Created", Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
counter++;
Toast.makeText(this, " Service Started" + " " + counter, Toast.LENGTH_SHORT).show();
SaveForm handler = new SaveForm(getApplicationContext());
handler.setobj(getApplicationContext());
handler.setText(Formact.sendform, Formact.listString);
handler.stratConnection();
String m = "";
int val = 0;
try{
Log.e("val",SaveForm.msg);
if(SaveForm.msg!=null)
{
m=SaveForm.msg.substring(SaveForm.msg.length() - 1);
}
val=Integer.parseInt(m);
Log.e("val",m);
if(val>0)
{
Toast toast = Toast.makeText(getApplicationContext(), "Data saved", 100);
toast.show();
save=true;
MyService.this.stopSelf();
// alarm.cancel(pintent);
if(alarm!=null)
{
try{
alarm.cancel(pintent);
}
catch(Exception e)
{
Toast toasdst = Toast.makeText(getApplicationContext(), "Massi", 100);
toasdst.show();
}
alarm=null;
}
}
}
catch(Exception e)
{
Toast toast = Toast.makeText(getApplicationContext(), "Data Not saved", 100);
toast.show();
///responseStr = responseStrr;
}
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
super.onDestroy();
if(save)
{
try{
stopSelf();
}
catch(Exception e)
{
Toast.makeText(this, "Head Bang", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
}
}
}
I had set the alarm.cancle but it throws exception because alarm is already null
I had also tried this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try{
// String parameter = intent.getStringExtra("param_name");
if(save){
stopSelf();
}
}catch(Exception ex){
}
return startId;
}
But nothing works service starts again and again.
One more thing if I did not close the application than every thing works perfect the alarm is canceled but when I close the application and expect to run it same it background it start creating again and again.
Help please.
1.Do not use onStart(), in docs:
onStart(Intent intent, int startId)
This method was deprecated in API level 5. Implement onStartCommand(Intent, int, int) instead.
Use onStartCommand instead and return START_NOT_STICKY or START_STICKY not startId.
2. It seems that you are starting a connection handler.stratConnection(); if you are binding anything to it using bindService(), then you need to unbind it from the service using unbindService(mConnection). As given in docs:
Disconnect from an application service. You will no longer receive calls as the service is restarted, and the service is now allowed to stop at any time.
If you are not binding anything then return null in onBind().
#Override
public IBinder onBind(Intent intent) {
return null;
}
3. Use super.onDestroy() like this:
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
super.onDestroy();
/***** No need to put this as it is already going to be destroyed
if(save)
{
try{
stopSelf();
}
catch(Exception e)
{
Toast.makeText(this, "Head Bang", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
}
}
*****/
}
4. Cancel the alarm by alarm.cancel(pintent) before calling stopSelf().
if(alarm!=null)
{
try{
alarm.cancel(pintent);
}
catch(Exception e)
{
Toast toasdst = Toast.makeText(getApplicationContext(), "Massi", 100);
toasdst.show();
}
alarm=null;
}
MyService.this.stopSelf();
5. You are using alarm and pintent without initializing it. It is not initialized in your code.
6. Stop service in your activity by using context.stopService(intent), using the same intent as Intent intent = new Intent(Formact.this, MyService.class);.
As you are storing the data to the server by using
handler.setText(Formact.sendform, Formact.listString);
Simply once the data is saved make
Formact.sendform=null
Formact.listString=null
when these values are null the application will throw a exception catch it in a catch block and use this line to close
MyService.alarm.cancel(MyService.pintent);
MyService.this.stopService();
service will not start again.
Related
Android will kill some service when memory is not enough.
Like this:
I know I can use foreground service to prohibit android to kill my service
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
try {
Notification notification = new Notification(R.mipmap.ic_launcher,"this is service", System.currentTimeMillis());
Intent intent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,intent , 0);
notification.setLatestEventInfo(this, "myapp", "myservice", contentIntent);
notification.flags =Notification.FLAG_AUTO_CANCEL;
startForeground(123,notification);
}
catch(Exception e)
{
stopSelf();
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
But this will display a notification on screen
I would rather kill service than display notification, but I also don't want to display stopped message.
I found some app, it can display no message when android kills it.
e.g. Screen Dimmer
How can I prohibit android to display app stopped message?
Check this: https://stackoverflow.com/a/32229266/2965799
According to that I have used the following code to handle the exception. I wanted to display another message so I added my own message however if you use his answer there will be no messages.
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
new Thread() {
#Override
public void run() {
Looper.prepare();
Toast.makeText(getActivity(),"Your message", Toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
try
{
Thread.sleep(4000); // Let the Toast display before app will get shutdown
}
catch (InterruptedException e) { }
System.exit(2);
}
});
One way is to implement a UncaughtExceptionHandler with your own custom failure code. The API to install your handler is this:
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh);
The class is documented here. As a very basic example:
import java.lang.Thread.UncaughtExceptionHandler;
public final class CrashHandler implements UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
android.util.Log.wtf("My app name", "Oops, caught it dying on me!");
}
}
A full working example is available here.
I've create an application, VPN service, which will block internet packets. Everything is working fine but now I want to stop this VPN service on a button click event so that packets are not blocked anymore.
I've tried to use stopService(name); and stopSelf();
but nothing happened. What am I doing wrong?
public class VpnServiceCls extends VpnService {
private Thread b;
private ParcelFileDescriptor c;
private PendingIntent a;
Builder builder = new Builder();
private static final String TAG = "VpnService";
#Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, "you are in jghbgjyhb");
if (b != null) {
Log.d(TAG, "you are in destroy2");
b.interrupt();
}
}
public void StopMyVPN()
{
Log.d(TAG, "you are in jghbgjyhb 898");
stopSelf();
if (b != null) {
Log.d(TAG, "you are in destroy");
b.interrupt();
}
b.stop();
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
b= new Thread(new Runnable() {
#Override
public void run() {
try{
//here is my logic which is working fine
}
}
catch(Exception e)
{
Log.d(TAG, "you are out "+e.toString());
}
}
});//start the service
b.start();
return START_STICKY;
}
}
on button click i am calling StopMyVPN() function but notting happen
you must close and set null interface of vpn .mInterface is vpn interface.
public void StopMyVPN() {
try {
if (mInterface != null) {
mInterface.close();
mInterface = null;
}
isRunning = false;
} catch (Exception e) {
}
stopSelf();
}
you could Bind Activity to your service for calling StopMyVPN.
I also struggled with this issue. At the end I found that my problem was caused by parcelFileDescriptor which I was not closing, and that kept my service from destroy.
private fun stop(){
try {
parcelFileDescriptor.close()
} catch (ex: IOException) {
Log.e(TAG,"parcelFileDescriptor.close()", ex)
}
stopForeground(true)
stopSelf()
}
In a typical android service you can call stopSelf(); but in this case as it is VpnService, same should work only when you closed the interfaces.
So in VpnService when you build a Tun by doing establish() and get the interface. Now if you want to shutdown your VPN tunnel, then you need to first close this interface and then you need to stop all the threads that you have started, and then you are free to call stopSelf() and it should work.
I have a service that I am wanting to execute a task every minute in the background. It does not need to execute the task whenever the phone is asleep, only when the user is actively using it. I am trying to do this with an IntentService which is set up as follows:
public class CounterService extends IntentService{
public CounterService() {
super("CounterService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
#Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(this, "onhandleintent", Toast.LENGTH_SHORT).show();
while(true)
{
//one minute is 60*1000
try {
Thread.sleep(5 * 1000);
Toast.makeText(getApplicationContext(), "getting app count", Toast.LENGTH_LONG).show();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Right now to get the functionality working I simply want it to display a toast every 5 seconds, I will change it to one minute later. If I have the while(true) commented out, then the "onhandleintent" message is displayed. However if I have the following code run, neither of the Toasts display. How can I fix this?
This will send an intent to your service every minute without using any processor time in your activity in between
Intent myIntent = new Intent(context, MyServiceReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 60); // first time
long frequency= 60 * 1000; // in ms
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), frequency, pendingIntent);
Adjust MyServiceReceiver.class to match your target service or activity.
The documentation provides more details to fine-tune your calls like whether you want exact timing, execution at a specific time of the day ...
You need to exit the main thread to avoid risking a ANR.
Instead add a Handler
Handler mHandler = new Handler();
...
#Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(this, "onhandleintent", Toast.LENGTH_SHORT).show();
mHandler.postDelayed( ToastRunnable, 5000);
//while(true)
//{
//one minute is 60*1000
//try {
// Thread.sleep(5 * 1000);
// Toast.makeText(getApplicationContext(), "getting app count",
//Toast.LENGTH_LONG).show();
//} catch (InterruptedException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
//}
//}
}
final Runnable ToastRunnable = new Runnable(){
public void run(){
Toast.makeText(getApplicationContext(), "getting app count",
Toast.LENGTH_LONG).show();
mHandler.postDelayed( ToastRunnable, 5000);
}
}
Do it like this
private void ping() {
try {
//Your code here or call a method
} catch (Exception e) {
Log.e("Error", "In onStartCommand");
e.printStackTrace();
}
scheduleNext();
}
private void scheduleNext() {
mHandler.postDelayed(new Runnable() {
public void run() { ping(); }
}, 60000);
}
public int onStartCommand(Intent intent, int x, int y) {
mHandler = new android.os.Handler();
ping();
return START_STICKY;
}
I have try build a android application that use a thread inside a service, the service and the thread run with well, but when i stop and destroy the service, the thread still live, so when i run again the application there are 2 thread in the application, so i wannt to know how i can destroy the thread.
anybody can help me to solve the problem ?
here my service class :
public class MyService extends Service{
Handler handler;
static String toast_msg;
Thread t;
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Congrats! MyService Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onStart(Intent intent, int startId) {
/* Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
//Note: You can start a new thread and use it for long background processing from here.*/
toast_msg = "Horas";
super.onStart(intent, startId);
Toast.makeText(getApplicationContext(), toast_msg, Toast.LENGTH_LONG)
.show();
handler = new Handler() {
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
Toast.makeText(getApplicationContext(), toast_msg,
Toast.LENGTH_LONG).show();
}
};
t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
t.sleep(5000);
// Toast.makeText(getApplicationContext(), "Horas",
// Toast.LENGTH_LONG).show();
handler.sendEmptyMessage(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
t.start();
}
#Override
public void onDestroy() {
Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
//t.interrupt();
handler.removeCallbacks(t);
super.onDestroy();
t.currentThread().interrupt();
}
}
t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
if(flag){//here add a flag
return;
}
t.sleep(5000);
// Toast.makeText(getApplicationContext(), "Horas",
// Toast.LENGTH_LONG).show();
handler.sendEmptyMessage(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
t.start();
public void onDestroy() {
Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
//t.interrupt();
handler.removeCallbacks(t);
super.onDestroy();
flag = false;//here set flag to false
}
You may want to consider using Service or IntentService instead, as these provide better management of threads, pausing, restarting etc.
See the Android IntentService documentation, or this other StackOverflow question and answer session. There's not much call to be kicking off your own threads these days, as there's better threading/service management features provided by the Android API/SDKs.
These are much more stable, optimised, and (in my opinion) neater and cleaner to use than spinning up a raw thread and trying to manage it yourself, especially if you're not catering for your app suddenly being killed because the battery went flat or the user doing something unexpected.
Can anyone tell me the way to keep a Service always running or restarting itself when the user close it? I've watched that facebook services restart when i clear memory.
I don't want to make ForegroundServices.
You should create a sticky service. Read more about it here.
You can do this by returning START_STICKY in onStartCommand.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Read also about application:persistent which is "Whether or not the application should remain running at all times". This is more troublesome - System will try not to kill your app which will effect others in the system, you should be careful using it.
I copied this from a service I used in an app I did before.
ITS IMPORTANT TO NOT UPDATE ANY UI. because you have no user interface in services. this applies to Toasts as well.
good luck
public class nasserservice extends Service {
private static long UPDATE_INTERVAL = 1*5*1000; //default
private static Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
_startService();
}
private void _startService()
{
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
doServiceWork();
}
}, 1000,UPDATE_INTERVAL);
Log.i(getClass().getSimpleName(), "FileScannerService Timer started....");
}
private void doServiceWork()
{
//do something wotever you want
//like reading file or getting data from network
try {
}
catch (Exception e) {
}
}
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
#Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
// if (MAIN_ACTIVITY != null) Log.d(getClass().getSimpleName(), "FileScannerService stopped");
}
}