Infinite IntentService stops working when there is no breakpoint - android

I have got an infinite IntentService meant to enable scanner for all the time application is alive. And whenever there is a breakpoint - it works fine. But when I remove a breakpoint from a loop - it stops working after some time. And then again when I put a breakpoint - it starts working again. What the heck? How can I fix this?
protected void onHandleIntent(#Nullable Intent intent)
{
final Handler handler = new Handler();
handler.post(new Runnable()
{
#Override
public void run()
{
while(true)
{
if (!blocked)
{
blocked = true;
String received = GlobalAccess.scan.scan(1000);
if (received != null && !received.isEmpty())
{
//TODO: some stuff here
}
blocked = false;
}
else
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
});
}
EDIT
I have created my CustomService with
#Override
public void onCreate()
{
super.onCreate();
scheduledExecutorService = Executors.newScheduledThreadPool(1);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
final Handler handler = new Handler();
Runnable runnable = new Runnable()
{
#Override
public void run()
{
while(true)
{
if (!blocked)
{
blocked = true;
String received = GlobalAccess.scan.scan(1000);
if (!Objects.equals(received, null) && !received.isEmpty())
{
//TODO: some stuff here
}
blocked = false;
}
else
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
};
ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(runnable, 0, TimeUnit.MILLISECONDS);
return START_STICKY;
}
But it has exact same bahavior as IntentService

Thanks to #CommonsWare I have managed to solve my problem.
This is the solution:
public class ScanService extends Service
{
ScheduledExecutorService scheduledExecutorService;
#Override
public void onCreate()
{
super.onCreate();
scheduledExecutorService = Executors.newScheduledThreadPool(1);
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Runnable runnable = new Runnable()
{
#Override
public void run()
{
String received = GlobalAccess.scan.scan(1000);
if (!Objects.equals(received, null) && !received.isEmpty())
{
//TODO: some stuff here
}
}
};
scheduledExecutorService.scheduleWithFixedDelay(runnable, 0, 50, TimeUnit.MILLISECONDS);
return START_STICKY;
}
}

Related

Application will be slow when service runs in the background

I am using a service in my application in order to get data from the server and save received data in my local database.
But when I am using the application and my service will run in the background the application works too slow.
This is my service class that I used:
public class InternetService extends Service implements Loader.OnLoadCompleteListener<Cursor> {
public static final int notify = 5 * 60 * 60 * 1000; //interval between two services(Here Service run every 1 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
private ArrayList<FileModel> failedIDDownloads = new ArrayList<>();
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "my_package";
Intent intent;
int counter = 0;
private CursorLoader cursorLoader;
private EncycDatabase encycDB;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
cursorLoader = new CursorLoader(this, Uri.parse(EncycDatabase.CONTENT_PROVIDER_URL),
null, null, null, null);
cursorLoader.registerListener(1, this);
cursorLoader.startLoading();
mHandler.removeCallbacks(sendUpdatesToUI);
mHandler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the cursor loader
if (cursorLoader != null) {
cursorLoader.unregisterListener(this);
cursorLoader.cancelLoad();
cursorLoader.stopLoading();
}
}
#Override
public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
encycDB = new EncycDatabase();
try {
while (cursor.moveToNext()) {
G.TOKEN = (cursor.getString(cursor.getColumnIndex("user_session_token")));
}
populateEncyclopediaData();
Thread searchTagThread = new Thread(new Runnable() {
#Override
public void run() {
populateSearchTagsEncyc();
populateSearchTags();
}
});
G.handler.postDelayed(new Runnable() {
#Override
public void run() {
checkForDownloadFiles();
}
},10 *60* 1000);
searchTagThread.start();
} catch (Exception e) { //When happened an error in getting Token!
e.printStackTrace();
}
}
private void populateEncyclopediaData() {
final APIService service = ServiceGenerator.createService(APIService.class,
new PreferenceManager(G.context).getLastUpdateForEncyclopediaData(), G.TOKEN);
service.getLastChanges()
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.subscribe(new Observer<Response<ArrayList<ServerLastChangesModel>>>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Response<ArrayList<ServerLastChangesModel>> response) {
Log.i("LOGO_Encycloedia", "Request code: " + response.code());
if (response.code() == 200) {
G.encyclopediaArray.clear();
for (int i = 0; i < response.body().size(); i++) {
EncyclopediaModel lcModel = new EncyclopediaModel();
lcModel.setEncyclopedia_id(response.body().get(i).getEncyclopediaId());
lcModel.setEncyclopedia_title(response.body().get(i).getEncyclopediaTitle());
lcModel.setEncyclopedia_modified_date(response.body().get(i).getEncyclopediaModifiedDate());
lcModel.setEncyclopedia_deleted(response.body().get(i).getEncyclopediaDeleted());
lcModel.setEncyclopedia_content_id(response.body().get(i).getEncyclopediaContentId());
lcModel.setEncyclopedia_out_desc_text_id(response.body().get(i).getEncyclopediaOutDescTextId());
lcModel.setEncyclopedia_in_desc_text_id(response.body().get(i).getEncyclopediaInDescTextId());
lcModel.setEncyclopedia_order_in_parent(response.body().get(i).getEncyclopediaOrderInParent());
lcModel.setEncyclopedia_parent_id(response.body().get(i).getEncyclopediaParentId());
lcModel.setEncyclopedia_is_inline_parent(response.body().get(i).getEncyclopediaIsInlineParent());
lcModel.setEncyclopedia_style_sheet(response.body().get(i).getEncyclopediaStyleSheet());
G.encyclopediaArray.add(lcModel);
}
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
try {
encycDB.insertIntoEncyclopediaDB(G.encyclopediaArray);
new PreferenceManager(G.context).writeLastUpdateForEncyclopediaData();
} catch (Exception e) {
e.printStackTrace();
}
populateContentData(encycDB.getContentIdsFromEncyclopedia());
}
});
}
As you can see, I used threads, but it doesn't help!
I can't find out where is the problem.
The Service runs in background but it runs on the Main Thread of the application. And IntentService runs on separate worker thread.
Move your code to IntentService.

why restart the service

i have a problem in my service, the service is runnig from MainActivity (i am doing test) and extends of service.
i want to use the service from foreground and background (when the app is closed) and i already have my first problem:
my service(have a counter that is displayed by LOG) is restarting when i close the app.
also i want to be able to use the service with the open app and close app, in other words to use both the Service Started and Link Service
public class MyService extends Service {
private Thread backgroundThread;
private boolean isRunning;
public MyService() {
Log.e("MyService","constructor");
}
#Override
public void onCreate() {
super.onCreate();
isRunning = false;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
Log.e("onStartCommand","Servicio Llamado");
if (!this.isRunning) {
Log.e("onStartCommand","hilo iniciandose");
this.backgroundThread = new Thread(myTask);
runTask();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("onDestroy","servicio destuido");
}
private void runTask(){
this.isRunning = true;
this.backgroundThread.start();
}
private Runnable myTask = new Runnable() {
public void run() {
Log.e("myTask","hilo iniciado");
int i = 0;
do{
pauseService();
Log.e("myTask","hilo contador: "+i);
//Toast.makeText(getApplicationContext(),"CONTADOR = "+j, Toast.LENGTH_SHORT).show(); //no working :(
i++;
}while (i<10);
/*
//linea de detencion del servicio
//stopSelf();
isRunning=false;
backgroundThread.interrupt();
//backgroundThread = new Thread(myTask);
*/
Log.e("myTask","hilo cerrado");
}
};
private void pauseService(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
In main Activity
Intent intent = new Intent(MainActivity.this,MyService.class);
intent.putExtra("iteraciones",10);
startService(intent);
why because the service restarts when I close the application and how can I avoid it?

Two Thread on Service

I want to operate two threads in the service.
I want to operate pThread only once in the onCreate
and
I want to continue to operate t-Thread in the onStartCommand.
If two threads operate independently, it works correctly.
but When operating as shown in the following source, it works incorrectly.
Perhaps, t-thread seems to operate before pThread is complete.
I want to t-Thread is operating after pThread is complete.
The source code is below.
public class BeaconService extends Service {
CentralManager centralManager;
private final String SERVER_ADDRESS = "http://xxx.xxx.xxx.xxx";
Handler handler;
XmlParser xmlGetter = new XmlParser();
Thread t;
Thread pThread;
String result = "d5756247-57a2-4344-915d-9599497940a7";
String text;
int count=0;
HashMap<String, Long> key = new HashMap<String, Long>();
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onCreate(){
super.onCreate();
setCentralManager();
handler = new Handler(Looper.getMainLooper());
t = new Thread(new Runnable() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
centralManager.startScanning();
}
});
}
});
pThread = new Thread(new Runnable() {
#Override
public void run() {
try{
URL url = new URL(SERVER_ADDRESS + "/Beacon_Infor.php?");
Log.i("url","url : "+url);
url.openStream();
Log.i("stream","success");
}catch(Exception e){
Log.e("Error", "Error : " + e.getMessage());
}
}
});
pThread.start();
Log.i("Service", "Start");
Toast.makeText(this, "Service Start", Toast.LENGTH_SHORT).show();
key=xmlGetter.getXmlHash("result.xml");
Log.i("beacon hash", "hash : " + key);
}
public int onStartCommand(Intent intent, int flags, int startId){
Log.i("onStartCommand", "Start");
t.start();
return START_STICKY;
}
public void onDestroy(){
Toast.makeText(this, "Service End", Toast.LENGTH_SHORT).show();
if(centralManager.isScanning()) {
centralManager.stopScanning();
}
centralManager.close();
super.onDestroy();
}
}

How can I put Toast in a Runnable of a Service?

I have a service which contains a Timer and TimerTask for receiving data from Webservice in periods of time. everything works fine except Toast. I want to show a Toast to user in procSendMapMovements but i get exception. How can I use Toast in it?
class taskSendMapMovements extends TimerTask {
#Override
public void run() {
hhSendMapMovements.sendEmptyMessage(0);
}
};
// /////////////////////
final Runnable rSendMapMovements = new Runnable()
{
public void run()
{
procSendMapMovements();
}
};
final Handler hhSendMapMovements = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
performOnBackgroundThread(rSendMapMovements);
return false;
}
});
// /////////////////////
public void procSendMapMovements() {
try {
Toast.makeText(SrvDataExchange.this,
"some texts"
Toast.LENGTH_SHORT).show();
// exception here
// my process
} catch (Exception e) {
}
}
#Override
public void onStart(Intent intent, int startId) {
try {
timerSendMapMovements = new Timer();
timerSendMapMovements
.schedule(new taskSendMapMovements(),
10*60*1000,
10*60*1000);
//
} catch (NumberFormatException e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
Create a handler to display toast.
Use following:
where you want to display toast call:
//printToast.sendEmptyMessage();//If you dont want to send no paramter
//if you want to send some object to handler
/*
Message msg=printToast.obtainMessage();
msg.obj=objToSent;
printToast.sendMessage(msg);
*/
final Handler printToast= new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText....;
}
});
**
Handler printToast= new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText....;
}
});
your Runnable
{
run()
{
do what ever you want
printToast.sendMessage(printToast.obtainMessage());
}
}
**

How can I prevent UI hang, when my service runs a TimerTask?

I have a service which contains a Timer and TimerTask for receiving data from Webservice in periods of time. When my TimerTask runs, the UI hangs until the Webservice process complete. How can I put my task in a thread to prevent the UI hanging?
My code:
Timer timerSyncFull = new Timer();
class taskSyncFull extends TimerTask {
#Override
public void run() {
hSyncFull.sendEmptyMessage(0);
}
};
final Handler hSyncFull = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
procSyncFull();
return false;
}
});
public void procSyncFull() {
try {
// My webservice process
} catch (Exception e) {
}
}
#Override
public void onStart(Intent intent, int startId) {
timerSyncFull = new Timer();
timerSyncFull.schedule(new taskSyncFull(), 5*60*1000,
5*60*1000);
}
Use AsyncTasks or attach your Handler to another Looper thread.
I used the following code and my problem solved:
class taskSendMapMovements extends TimerTask {
#Override
public void run() {
hhSendMapMovements.sendEmptyMessage(0);
}
};
// /////////////////////
final Runnable rSendMapMovements = new Runnable()
{
public void run()
{
procSendMapMovements();
}
};
final Handler hhSendMapMovements = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
performOnBackgroundThread(rSendMapMovements);
return false;
}
});
// /////////////////////
public void procSendMapMovements() {
try {
showToast("some text");
//My Main Process
} catch (Exception e) {
}
}
#Override
public void onStart(Intent intent, int startId) {
try {
timerSendMapMovements = new Timer();
timerSendMapMovements
.schedule(new taskSendMapMovements(),
10*60*1000,
10*60*1000);
//
} catch (NumberFormatException e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
final Handler hToast = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText(SrvDataExchange.this,
msg.getData().getString("msg"),
Toast.LENGTH_LONG).show();
return false;
}
});
private void showToast(String strMessage) {
Message msg = new Message();
Bundle b = new Bundle();
b.putString("msg", strMessage);
msg.setData(b);
hToast.sendMessage(msg);
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
Simply invoke your procSyncFull() method in thread or asyncTask.
final Handler hSyncFull = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Thread thread=new Thread()
{
public void run(){
procSyncFull();
}
}
return false;
}
});
private Handler webserviceCompletionHandler=new Handler()
{
#Override
public boolean handleMessage(Message msg) {
return false;
}
};
use AsyncTask carry out your execution in doInBackground() and populate it in onPostExecute()
AsyncTask Example

Categories

Resources