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().
Related
I'm looking on a way to run this task repeatedly with the listener. Right now, this is working but I'm looking on a way to make it repeatedly every 10 seconds.
Activity
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
VolleyRequest.makeRequest(this, URL, listenerResponse, listenerError);
}
private static final String URL = "https://naqil.ma/random.php";
private Response.Listener<JSONObject> listenerResponse = new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Toast.makeText(SecondActivity.this, "Resonse " + response.toString(), Toast.LENGTH_LONG).show();
}
};
private Response.ErrorListener listenerError = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(SecondActivity.this, "Error " + error, Toast.LENGTH_LONG).show();
}
};
}
Class making request
public class VolleyRequest {
public static void makeRequest(Context context, String url,
Response.Listener<JSONObject> listenerResponse, Response.ErrorListener listenerError) {
JsonObjectRequest requestWeather = new JsonObjectRequest(Request.Method.GET, url, null, listenerResponse,
listenerError);
Volley.newRequestQueue(context).add(requestWeather);
}
}
````
(Adapted from this answer: https://stackoverflow.com/a/10156550/2711811 )
Basically use a handler to reschedule request every 10 seconds. Handler is attached to main looper by virtue of creating it in onStart.
First, remove the VolleyRequest.makeRequest from onCreate.
Add members to SecondActivity:
private Handler myHandler;
private Runnable myRunnable;
In onStart of SecondActivity :
protected void onStart() {
super.onStart();
// Start issuing VolleyRequests repeating every 10 seconds.
myHandler = new Handler();
myHandler.post(new Runnable() {
#Override
public void run() {
SecondActivity.this.myRunnable = this;
VolleyRequest.makeRequest(
SecondActivity.this,
URL,
SecondActivity.this.listenerResponse,
SecondActivity.this.listenerError);
SecondActivity.this.myHandler.postDelayed(this, 10000);
}
};
}
And stop the repeated requests when the activity is stopped: in onStop of SecondActivity:
protected void onStop() {
super.onStop();
// check that it actually ran at least once - can't be null.
if (myRunnable != null) {
myHandler.removeCallbacks(myRunnable);
}
}
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) {
}
}
}
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);
I have created a Timer through Stopwatch class and implement it successfully in activity.
But i want to continue the timer after closing the application, so i used Service and put the method inside this. Something like below:
MyService.java:
Stopwatch stopwatch = Stopwatch.createStarted();
String workingTime1 = "";
void startThreadUpdateTimer() {
final DecimalFormat format = new DecimalFormat("00");
Timer T = new Timer();
T.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
workingTime1 = "Your effort is "
+ format.format(Double.valueOf(stopwatch
.elapsed(TimeUnit.HOURS)))
+ ":"
+ format.format(Double.valueOf(stopwatch
.elapsed(TimeUnit.MINUTES)))
+ ":"
+ format.format(Double.valueOf(stopwatch
.elapsed(TimeUnit.SECONDS)))
+ " till now for the day";
SwipePage.efforttimer.setText(workingTime1);
}
});
}
}, 1000, 1000);
}
void runOnUiThread(Runnable runnable) {
handler.post(runnable);
}
efforttimer is the TextView in which I want to show my effort time. I think binding service or broadcastreceiver will help here. Implement many ways but not succeed yet.
All helps and suggestions are mostly appreciable.
Thanks
LocalBroadcastManager will be the simplest solution in your case.
In your MyService you'll need this code:
public class MyService extends Service {
public static final String ACTION_UPDATE = "MyServiceACTION_UPDATE";
...
private void updateEmitterMethod() {
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(ACTION_UPDATE));
}
}
While in your Activity you'll have:
private BroadcastReceiver mMyServiceUpdateReciever;
...
#Override
public void onResume() {
super.onResume();
mMyServiceUpdateReciever = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
onUpdateMethod();
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(mMyServiceUpdateReciever, new IntentFilter(MyService.ACTION_UPDATE));
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMyServiceUpdateReciever);
}
I have an activity in which I call Service on background, I am quite new to AIDL
my codes are as follows:
on Activity
//declaration
private Intent mIntentInvenueService;
private IInvenueService mIInvenueService;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIntentInvenueService = new Intent(this, InvenueService.class);
startService(mIntentInvenueService);
}
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIInvenueService = IInvenueService.Stub.asInterface(service);
try {
mIInvenueService.registerCallback(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
mIInvenueService = null;
try {
mIInvenueService.unregisterCallback(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
private final IInvenueServiceCallback.Stub mCallback = new IInvenueServiceCallback.Stub() {
#Override
public void onReceiveResponse() throws RemoteException {
runOnUiThread(new Runnable() {
public void run() {
if (flagChanged){
}
else
{
cAdapter.notifyDataSetChanged();
}
}
});
}
};
public void onResume() {
super.onResume();
bindService(mIntentInvenueService, mServiceConnection, BIND_AUTO_CREATE);
}
#Override
public void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
unregisterReceiver(mBroadcastReceiver);
}
ON MY SERVICE:
private final RemoteCallbackList<IInvenueServiceCallback> mCallbacks = new RemoteCallbackList<IInvenueServiceCallback>();
private boolean isUpdated = false;
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IInvenueService.Stub mBinder = new IInvenueService.Stub() {
#Override
public void startProcess() throws RemoteException {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
Toast.makeText(......).show()// Toast Here
}
}, 60000, 60000);
}
#Override
public void unregisterCallback(IInvenueServiceCallback callback)
throws RemoteException {
mCallbacks.unregister(callback);
}
#Override
public void registerCallback(IInvenueServiceCallback callback)
throws RemoteException {
mCallbacks.register(callback);
}
};
My AIDL:
interface IInvenueService {
void startProcess();
void registerCallback(IInvenueServiceCallback callback);
void unregisterCallback(IInvenueServiceCallback callback);
}
My Question is why is that the Toast not showing? Am I missing something that start process isnt working?
Any Help?
You should show Toasts from the UIThread, using a TimerTask will cause it to run on a seperate thread.
Try posting a runnable with the Toast to a Handler.