Android - Explanation about AsyncTask in Service class - java

I've a task to running service every 3 second, the service will execute asynctask to checking sqlite and sending data into server
Code of myService.class
/* import foo.foo.foo */
public class myService extends Service {
public Runnable mRunnable = null;
private boolean mRunning = false;
Handler mHandler = new Handler();
IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class LocalBinder extends Binder {
public myService getServerInstance() {
return myService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("Service"," onstart kepanggil ga?");
mRunnable = new Runnable() {
#Override
public void run() {
Log.d("Service","SERVICE RUN");
SharedPreferences pref = getSharedPreferences("wit_player_shared_preferences", MODE_PRIVATE);
String servcheck = pref.getString("serviceChecker", null);
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
int countFlagAuditID = db.getCountFlagAuditID();
int countNeedToSend = db.getCountContact();
if (countNeedToSend > 0){
Log.d("countNeedToSend : ", String.valueOf(countNeedToSend));
sending a = new sending();
try {
if(servcheck.equals("no")){
Log.d("Service","SERVICE TRY CALL SENDING");
a.execute().get();
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
if (countFlagAuditID > 0){
Log.d("countFlagAuditID : ", String.valueOf(countFlagAuditID));
if(servcheck.equals("no")){
Log.d("Service","SERVICE TRY CALL SENDGET");
sendget b = new sendget();
b.execute();
}
}
db.close();
mHandler.postDelayed(mRunnable, 3 * 1000);
}
};
mHandler.postDelayed(mRunnable, 3 * 1000);
return START_STICKY;
}
//async task
private class sending extends AsyncTask<Void, Void, String >
{
#Override
protected void onPreExecute() {
Log.i("SENDING", "start sending");
SharedPreferences pref = getSharedPreferences("wit_player_shared_preferences", MODE_PRIVATE);
pref.edit().putString("serviceChecker", "yes").commit();
if (serv.equals("yes")){
Log.i("stop service", "service di stop");
stopSelf();
}
}
#Override
protected String doInBackground(Void... params) {
//send data to server
}
#Override
protected void onPostExecute(String result) {
SharedPreferences pref = getSharedPreferences("wit_player_shared_preferences", MODE_PRIVATE);
pref.edit().putString("serviceChecker", "no").commit();
}
}
private class sendget extends AsyncTask<Void, Void, String >
{
//execute post to server
}
}
I've a list of question about the code above:
to let my service run every 3sec I need to declare twice of mHandler.postDelayed(mRunnable, 3 * 1000);, if I'm declare the code just one, the service will run once, why it can be like that?
on sending asynctask I've add stopSelf() on onPreExecute() that mean the service will stop, but why doInBackground() task keep run?

Try to use timer instead of handler
private final Timer mTimer = new Timer();
mTimer.scheduleAtFixedRate(new LocationUpdateTask(), 0, 3000);
private class LocationUpdateTask extends TimerTask {
#Override
public void run() {
try {
//Do your stuff
} catch (Exception e) {
// TODO: handle exception
} catch (ExceptionInInitializerError in) {
}
}
}

Related

Can't stop foreground service stopSelf() and stopForeground(true) not working

I'm trying to stop my foreground service but it seems that my code not work properly
Intent intent = new Intent(SplashScreenActivity.this, DNSService.class);
stopService(intent);
And this is my service source:
public class DNSService extends VpnService {
public final static String DNS_MODEL = "DNSModelIntent";
private VpnService.Builder builder = new VpnService.Builder();
private ParcelFileDescriptor fileDescriptor;
private Thread mThread;
private boolean shouldRun = true;
private DatagramChannel tunnel;
private DNSModel dnsModel;
public static final String ACTION_CONNECT = DNSService.class.getName() + ".START";
public static final String ACTION_DISCONNECT = DNSService.class.getName() + ".STOP";
#Override
public void onDestroy() {
stopSelf();
stopForeground(true);
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
}
private void setTunnel(DatagramChannel tunnel) {
this.tunnel = tunnel;
}
private void setFileDescriptor(ParcelFileDescriptor fileDescriptor) {
this.fileDescriptor = fileDescriptor;
}
#Override
public int onStartCommand(final Intent intent, int p1, int p2) {
mThread = new Thread(() -> {
try {
dnsModel = intent.getParcelableExtra(DNS_MODEL);
setFileDescriptor(builder.setSession(DNSService.this.getText(R.string.app_name).toString()).
addAddress("192.168.0.1", 24).addDnsServer(dnsModel.getFirstDns()).addDnsServer(dnsModel.getSecondDns()).establish());
setTunnel(DatagramChannel.open());
tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
protect(tunnel.socket());
while (shouldRun)
Thread.sleep(100L);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
if (fileDescriptor != null) {
try {
fileDescriptor.close();
setFileDescriptor(null);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
mThread.start();
return Service.START_STICKY;
}
}
You have to close all running processes inside onDestroy() for your work to stop. The reason is that started thread is running on other process. So after you kill your service thread is still running.

AsyncTask not delaying operation in Handler

I'm writing application and I want to call AsyncTask from BroadCastReceiver initialized in Service.
I want to AsyncTask do some work in background delayed, but it seems like a Handler not working, because I'm getting in Logcat this output(in short):
05-18 20:33:01.396 19382-19382// D/AsyncTask: Sleeping for a while
Sleeping for a while
.
.
05-18 20:33:01.406 19382-19382// D/AsyncTask: Sleeping for a while
Sleeping for a while
.
.
Here is my code:
ExampleService.java:
import java.util.*;
import android.content.*;
import com.google.firebase.messaging.*;
import timber.log.*;
public class ExampleService extends FirebaseMessagingService {
private AnotherExample anotherExample;
#Override
public void onMessageReceived(final RemoteMessage message) {
Timber.d("onMessageReceived(): message: %s", message);
anotherExample = new AnotherExample();
if (message.getData() != null) {
processMessage(message.getData());
}
}
private void processMessage(Map<String, String> data) {
Timber.d("processMessage(): data: %s", data);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Timber.d("onReceiveScreenOff()");
anotherExample.create();
anotherExample.resume();
}
}, filter);
IntentFilter filter1 = new IntentFilter();
filter1.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Timber.d("onReceiveScreenOn()");
anotherExample.suspend();
}
}, filter1);
}
}
AnotherExample.java
public class AnotherExample {
AsyncTask asyncTask;
public void create() {
this.asyncTask = new MyAsyncTask();
}
public void resume() {
this.asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void suspend() {
this.asyncTask.cancel(true);
}
}
MyAsyncTask.java
public class MyAsyncTask extends AsyncTask {
private Handler handler;
private Runnable runnable;
private void setupRunnable() {
runnable = new Runnable() {
#Override
public void run() {
Log.d("AsyncTask", "Sleeping for a while");
}
};
}
#Override
protected Object doInBackground(Object[] objects) {
while (!isCancelled()) {
handler.postDelayed(runnable, 1000);
}
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
Log.d("AsyncTask", "Removing callbacks");
handler.removeCallbacks(runnable);
}
}
I don't know where the problem is, I also tried it with Thread.sleep(1000), but the result was same.
Is there any other way how to implement it?
Also I want to ask, is AsyncTask and BroadCastReceiver using same thread? Because it looks like BroadCastReceiver not getting information when screen is on.
Thanks for every advice.
I cannot reproduce your issue. My code seems to work fine.
Just call this:
private void testAsyncTaskDelay(){
TestEventsData test = new TestEventsData();
test.execute();
}
My TestEventsData class definition:
class TestEventsData extends AsyncTask<String, Integer, Boolean> {
Handler testHandler = new Handler();
#Override
protected Boolean doInBackground(String... params) {
Boolean success = false;
try {
long startTime = SystemClock.elapsedRealtime();
Log.e(TAG, "doInBackground Start " + startTime);
testHandler.postDelayed(new Runnable() {
#Override
public void run() {
long endTime = SystemClock.elapsedRealtime();
long diff = endTime - startTime;
Log.e(TAG, "run Start " + endTime);
Log.e(TAG, "run Start diff " + diff);
}
}, 3000);
}
catch (Exception ex) {
Log.e(TAG, "doInBackground --- " + ex.getMessage());
}
return success;
}
#Override
protected void onCancelled() {
}
#Override
protected void onPostExecute(Boolean success) {
try{
Log.e(TAG, "onPostExecute NOW");
}
catch(Exception ex){
Log.e(TAG, "onPostExecute" + ex.getMessage());
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
My output to logcat:
05-18 15:15:51.951 24329-24345/? E/MainActivity: doInBackground Start 1471880721
05-18 15:15:52.003 24329-24329/? E/MainActivity: onPostExecute NOW
05-18 15:15:54.953 24329-24329/com.asb.android.mcc E/MainActivity: run Start 1471883724
05-18 15:15:54.953 24329-24329/com.asb.android.mcc E/MainActivity: run Start diff 3003
Time difference 3003ms! Same time set in my postDelayed().

Wait until socket as service gets available

I have read about Thread sleep, Handler, Runnable, AsyncTask and TimerTask, tried Thread sleep but could not figure out how can I accomplish the task.
I have implemented socket.io.client-java as service and using Volley as well as multiple activities & fragments. I need as follow:
Check if socket is connected before making Volley request.
If socket is connected then process Volley request otherwise re-check socket connectivity (a maximum of 5 times with 1 second interval).
In case of failure in 5 attempts, show a Toast message and continue the Volley request.
I 'm using a common class to perform Volley requests and others.
Socket Service
public class SocketClient extends Service {
private Socket mSocket = null;
private static SocketClient iSocket;
public SocketClient() {
super();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onCreate(){
super.onCreate();
iSocket = this;
startSocket();
}
public static synchronized SocketClient getInstance(){return iSocket;}
private void startSocket(){
try {
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
//...
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
//...
}
}).on(...{...});
mSocket.connect();
} catch (URISyntaxException e){
e.printStackTrace();
}
}
public boolean isConnected(){ return (mSocket != null && mSocket.connected()); }
#Override
public void onDestroy(){
super.onDestroy();
mSocket.disconnect().close();
mSocket = null;
}
}
Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
Helpers.startServices(getApplicationContext(), 1);
}
#Override
protected void onResume() {
Helpers.getNotifed(); //A Volley Request
}
Helpers Class
public static void makeReq(Map<String, Object> params, String api, final Context context, final VolleyListener listener)
{
manager = new SessionManager(context);
final String url = baseURL + api;
int i = 0;
boolean ss = SocketClient.getInstance().isConnected();
Log.i(TAG, "Socket status" + ss);
while(i < 5 && !ss) {
try {
Log.i(TAG, "Socket status" + ss);
Log.i(TAG, "sleeping " + i);
Thread.sleep(1000);
ss = SocketClient.getInstance().isConnected();
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!ss)
Toast.makeText(context, "Operation interrupt!", Toast.LENGTH_LONG).show();
//Volley JSON Object Request
}
public static void startServices(Context context, int st) {
switch (st) {
case 1: //Socket
if (!isServiceRunning(context, SocketClient.class))
context.startService(new Intent(context, SocketClient.class));
break;
}
}
Issues:
Getting NullPointerException at boolean ss = SocketClient.getInstance().isConnected(); as class might not initialized yet.
ANR (Application Not Responding) because the main Thread is halted in while loop.
P.S.: I'm just a beginner in Android/Java so reply with clear code would be appreciable.

How to make a background service?

I need to execute some tasks when my application is closed.
I have made a service for do this and tried many things, but i don't have the good result.
If someone have a tutorial or some path to follow, it would be great
This is my service:
public class TrackersImporter extends Service {
private static TrackersImporter instance;
private static long refreshDelay = 1; // Minutes
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private boolean isInit = false;
public ArrayList<Tracker> trackers = new ArrayList<>();
public static TrackersImporter getInstance(){
if (instance == null)
instance = new TrackersImporter();
return instance;
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("TrackersImporter",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();
Message message = mServiceHandler.obtainMessage();
message.arg1 = startId;
mServiceHandler.sendMessage(message);
} catch (Exception e) {
Log.w("TrackersImporter", e.getMessage());
}
return START_STICKY;
}
public void addTracker(Tracker tracker) {
trackers.add(tracker);
}
protected void showToast(final String msg){
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
// Object responsible for
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
addTracker(Runkeeper.getInstance(MainActivity.getActivity()));
addTracker(Strava.getInstance(MainActivity.getActivity()));
startImport(MainActivity.getActivity().getBaseContext(), MainActivity.getActivity().getAppUser(), trackers);
stopSelf(msg.arg1);
}
/**
* Perform data imports.
* Imports are performed only 1 time.
* Additional calls to this method are equivalent to no-op.
* Call init() then performImport() for each TrackerImportable
* #param user user receiving the datas
*/
public void startImport(Context context, User user, ArrayList<Tracker> trackers) {
Context ctx = MainActivity.getActivity().getApplicationContext();
LocalDateTime now = new LocalDateTime();
if (Preferences.getPref(ctx, "tracker_import_date") == "")
Preferences.setPref(ctx, "tracker_import_date", now.toString());
LocalDateTime past = LocalDateTime.parse(Preferences.getPref(ctx, "tracker_import_date"));
long duration = new Duration(past.toDateTime(), now.toDateTime()).getStandardMinutes();
if (isInit)
return;
if (duration > refreshDelay) {
Preferences.setPref(ctx, "tracker_import_date", now.toString());
for (Tracker tracker : trackers) {
if (tracker.isEnabled() && Tracker.isUserEnabled(context, tracker.getName())) {
tracker.init();
tracker.performImport(user);
}
}
}
isInit = true;
}
}
}
This is my mainActivity
public class MainActivity extends BaseActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (ConnectivityUtil.isConnected(this.getApplicationContext())) {
initGoogleFit();
initTrackers(appUser);
}
}
private void initTrackers(User user) {
Intent trackersIntentService = new Intent(this, TrackersImporter.class);
trackersIntentService.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startService(trackersIntentService);
}
#Override
protected void onResume() {
...
if (ConnectivityUtil.isConnected(this.getApplicationContext())) {
initTrackers(appUser);
}
}
}
First Create one launcher Activity which is like your Main Activity.
In Activity "onCreate" Method you need to start Service and Do Some thing if you wont in Service "onStartCommand" Method.
public class MainActivity extends Activity {
ArrayList<Integer> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this,TrackersImporter.class);
}
public class TrackersImporter extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do something
Log.v(TAG ,"Service is started");
}
}
And also Register this Service at manifest.xml like this.
<service android:name=".TrackersImporter"></service>
if you like stop service
stopService(new Intent(MainActivity.this,TrackersImporter.class);

Android work in background

I got 3 activities ( A , B ,C ) and a service that I call to check if I got new messages from DB. It's a HTTP request . I need to make the request each 15 sec.
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(15000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here i call
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
How to make it work when i am changing activities ?
Option: Consider changing setup to have three fragments as your original activities, and a MainActivity that controls the repeat polling for messages to DB, as well as controlling the fragments.
#SuppressLint("SimpleDateFormat")
public class AlarmService extends Service {
private PendingIntent pendingIntent;
Handler mHandler;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
}
public void f() {
Toast t = Toast.makeText(this, "Service is still running",
Toast.LENGTH_SHORT);
t.show();
};
}
#Override
#Deprecated
public void onStart(Intent intent, int startId) {
Toast t = Toast.makeText(this, "Service started", Toast.LENGTH_SHORT);
t.show();
// TODO Auto-generated method stub
super.onStart(intent, startId);
mHandler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
f();
mHandler.postDelayed(this, 20000);
}
};
mHandler.postDelayed(r, 20000);
}
}
and in manifest use this
<service android:name="com.example.yourservice"></service>

Categories