I am developing a android app, which will update device location after 4 seconds interval and depending on the response received from the server it will open specific activity.
Problem 1) In some case it will open up a activity like incoming phone call with sound. I am facing problem when I am removing the app from recent app. I noticed the poll function is running twice at the same time, and multiple media is playing at the same time.
Problem 2) I am using Service intead of IntentService(I am a beginner and not sure which will be better). The background service should run even the phone goes to sleep mode, just like WhatsApp or other messenger run.
As the file is big enough, I am attaching only important part
public class TaxiNorrService extends Service implements LocationListener {
...
...
final Handler poll_handler = new Handler();
private NotificationManager mNM;
private final Actions actions = new Actions();
public Ringtone r;
private String newtext;
private Runnable BreakRunnable;
private Runnable poll_runnable;
private Handler BreakHandler;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
poll_runnable = new Runnable() {
#Override
public void run() {
if(!App.isAutoBreak()){
if(BreakHandler !=null){
BreakHandler.removeCallbacks(BreakRunnable);
}
if(r != null) {
if (r.isPlaying()) {
r.stop();
}
}
}
if (actions.checkPermission(getApplicationContext())) {
checkGPS();
if(isNetworkAvailable()){
if(App.isPollOn()){
poll(latitude, longitude);
}
}else{
if(BreakHandler !=null){
BreakHandler.removeCallbacks(BreakRunnable);
}
boolean foregroud = false;
try {
foregroud = new ForegroundCheckTask().execute(getApplication()).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
boolean background = isMyServiceRunning(TaxiNorrService.class);
if(foregroud == true && background == true && App.isAppForground()){
if(!App.isLoadingVisible()){
Intent intent = new Intent(TaxiNorrService.this, Loading_activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
}
}
poll_handler.postDelayed(this, 4000);
}
};
return Service.START_STICKY;
}
private void poll(double lat, double lon){
//Connected to API endpoint
}
...
...
#Override
public void onDestroy() {
if(r != null) {
if (r.isPlaying()) {
r.stop();
}
}
poll_handler.removeCallbacks(poll_runnable);
super.onDestroy();
}
}
I found the answer for my questions. The code written in the onStartCommand should be within onCreate function. This is because onCreate will execute when service starts first time, and onStartCommand will execute every time when you start the app. Please follow this topic,
Android - running a method periodically using postDelayed() call
Related
In my application I want use service for get request to server.
I should run this service for always and not stop it!
I write below code in service, but just show for 5 time and when receive to 5 step. then not show Toast!
But I want always getData() and show Toast.
Service class :
public class NotifyService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
new Thread(new Runnable() {
#Override
public void run() {
//Your logic that service will perform will be placed here
//In this example we are just looping and waits for 5000 milliseconds in each loop.
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(5000);
} catch (Exception e) {
}
if (isRunning) {
ExploreSendData sendData = new ExploreSendData();
sendData.setPageIndex(1);
sendData.setPageSize(10);
sendData.setShowFollows(false);
sendData.setShowMovies(true);
sendData.setShowNews(true);
sendData.setShowReplies(false);
sendData.setShowSeries(true);
sendData.setShowSuggestions(false);
InterfaceApi api = ApiClient.getClient().create(InterfaceApi.class);
Call<ExploreResponse> call = api.getExplore(new SharedPrefrencesHandler(NotifyService.this)
.getFromShared(SharedPrefrencesKeys.TOKEN.name()), sendData);
call.enqueue(new Callback<ExploreResponse>() {
#Override
public void onResponse(Call<ExploreResponse> call, Response<ExploreResponse> response) {
if (response.body().getData() != null && response.body().getStatusCode() != 401
&& response.body().getStatusCode() != 402) {
Toast.makeText(NotifyService.this, "Test Show message ever 5second", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ExploreResponse> call, Throwable t) {
}
});
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
I copy this service code from internet, but just show 5times. I want show always.
How can I edit my codes and fix it? Please help me. Thanks
The problem is not in the service, services start and continue living as long as the app is alive and android doesn't kill it. For an infinite loop replace the "for loop" with "While loop". The below loop doesn't end.
while (true) {
......
......
......
}
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 am working on below code to run a service in background,but the problem is i am not getting how to run the service indefinitely even though the app is closed,here on press of back my service is stopping.I have read many tutorials but still confused with this.
public class HelloService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
if (isRunning) {
Log.i(TAG, "Service running");
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
On Android there is NO way (at least for a third party app) to have a never ending process running. The system can always kill your service. So you can use a foreground service but the system can kill your service even in this case (even with low probability). In addition, you should consider that the cpu can go to sleep. So you should take a wakelock but in this way you can kill the user battery so it's not a good solution. My suggestion is to always work "on event" for example with a brodacast receiver that starts a intent service, it does some work and then exit. The always running processes are simply a wrong design choices on Android.
One Way is to use while loop but keep a check i.e
while(true) {
if (condition != true) {
Thread.sleep(time);
} else {
break;
}
}
In my app, I need to block sms, email and phone. I am not detecting for incoming or outgoing calls or sms. Simply, I have a service which will run in background and check if any of three processes is running. If they are running then my activity will open up when user clicks on dialer or sms app. So far, what I have tried, I am posting below:
Service Class
public class DialerService extends Service {
ActivityManager am;
List<RunningAppProcessInfo> mAppProcessInfosList;
private Runnable myRunnable;
boolean threadDone = true;
Handler mHandler;
boolean isLockedAppRunning = false;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onCreate() {
am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
mAppProcessInfosList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
mHandler = new Handler();
Log.v("Dialer Service", "onCreate called");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
myRunnable = new Runnable() {
#Override
public void run() {
isRestrictedAppRunning();
}
};
new Thread(new Runnable() {
public void run() {
while (threadDone) {
try {
mHandler.post(myRunnable);
} catch (Exception e) {
}
}
}
}).start();
return START_STICKY;
}
private void isRestrictedAppRunning() {
mAppProcessInfosList = am.getRunningAppProcesses();
for (int i = 0; i < mAppProcessInfosList.size(); i++) {
if (mAppProcessInfosList.get(i).processName
.equals("com.android.phone")
|| mAppProcessInfosList.get(i).processName
.equals("com.android.email")
|| mAppProcessInfosList.get(i).processName
.equals("com.android.mms")) {
isLockedAppRunning = true;
Intent dialogIntent = new Intent(getBaseContext(),
TestActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
this.threadDone = false;
}
}
This code is working but it has following issue:
It blocks all the apps, while my requirement is to restrict only those apps which I have listed to block. For e.g., if I am blocking phone and sms, my activity should open only on click of dialer and sms app, and not when I click on maps.
I am not getting how to do this.
When you detect that your blacklisted app is coming up, you need to bring down the running activity. A background service/thread will best handle the activity monitor. There are other internal methods using IActivityWatcher but the internal interface and related hidden APIs are subject to deprecation. I believe it is already deprecated in JB.
I'm trying to download multiple files using IntentService. The IntentService donwloads them okey as expected one at a time, the only problem is that when the Internet is down the intent service will not stop the donwload rather it will get stuck on the current thread. If I manage to stop the current thread it will continue running the other threads stored in its queue even though the internet connection is down.
It was suggested in another post that I use LinkedBlockingQueue and create my own Worker thread that constantly checks this queue for new threads. Now I know there are some increased overheads and thus performance issues when creating and destroying threads but that's not a concern in my case.
At this point, All I want to do is understand how IntentService works which as of yet I don't (and I have looked at the code) and then come up with my own implementation for it using LinkedBlockingQueue controlled by a Worker thread. Has anyone done this before ? Could provide a working example, if you feel uncomfortable providing the source code, pseudo code is fine by me. Thanks!
UPDATE: I eventually implemented my own Intent Service using a thread that has a looper which checks the queue which in turn stores the intents passed from the startService(intent).
public class MyIntentService extends Service {
private BlockingQueue<Download> queue = new LinkedBlockingQueue<Download>();
public MyIntentService(){
super();
}
#Override
public void onCreate() {
super.onCreate();
new Thread(queueController).start();
Log.e("onCreate","onCreate is running again");
}
boolean killed = false;
Runnable queueController = new Runnable() {
public void run() {
while (true) {
try {
Download d =queue.take();
if (killed) {
break;
}
else {
d.downloadFile();
Log.e("QueueInfo","queue size: " + queue.size());
}
}
catch (InterruptedException e) {
break;
}
}
Log.e("queueController", "queueController has finished processing");
Log.e("QueueInfo","queue size: " + queue.toString());
}
};
class Download {
String name;
//Download files process
void downloadFile() {
//Download code here
}
Log.e("Download","Download being processed is: " + name);
}
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
}
public void killService(){
killed = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Download d = new Download();
d.setName(intent.getStringExtra("VIDEOS"));
queue.add(d);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("stopSelf","stopSelf has been just called to stop the Service");
stopSelf();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I'm not so sure about the START_NOT_STICKY in the onStartCommand() method. If it's the right flag to return or not. Any clarification on that would be appreciated!
UPDATE: I eventually implemented my own Intent Service using a thread that has a looper which checks the queue which in turn stores the intents passed from the startService(intent).
public class MyIntentService extends Service {
private BlockingQueue<Download> queue = new LinkedBlockingQueue<Download>();
public MyIntentService(){
super();
}
#Override
public void onCreate() {
super.onCreate();
new Thread(queueController).start();
Log.e("onCreate","onCreate is running again");
}
boolean killed = false;
Runnable queueController = new Runnable() {
public void run() {
while (true) {
try {
Download d =queue.take();
if (killed) {
break;
}
else {
d.downloadFile();
Log.e("QueueInfo","queue size: " + queue.size());
}
}
catch (InterruptedException e) {
break;
}
}
Log.e("queueController", "queueController has finished processing");
Log.e("QueueInfo","queue size: " + queue.toString());
}
};
class Download {
String name;
//Download files process
void downloadFile() {
//Download code here
}
Log.e("Download","Download being processed is: " + name);
}
public void setName(String n){
name = n;
}