I can’t catch up - how to send Toast from Executors.newSingleThreadExecutor () in the run () method? In the debug I set a breakpoint, everything is fine, we go into the method, but the message does not appear in the emulator? And yet, in the same method, I send the intent to the receiver, the intent is sent, but the receiver does not receive it.
ExecutorService service:
public void start() {
service = Executors.newSingleThreadExecutor();
service.submit(new Runnable() {
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent intent = new Intent(ACTION_FOR_FRAGMENT);
sendBroadcast(intent);
service.shutdown();
}
});
}
I solved this problem, you can close the question. The essence of the problem was that I did not correctly implement the service methods.
Related
I need to make so backround job without blocking user UI, so I made a test IntentService to check how it's work, but this intent services block the UI.
Here my Code on start app ic start service:
Intent msgIntent = new Intent(this, AutoExchange.class);
startService(msgIntent);
AutoExchange.java
public class AutoExchange extends IntentService{
public AutoExchange() {
super("AutoExchange");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The problem is that this service block the main Ui, somethig I did wrong?
instead of thread.sleep() you can you handler
here is an example
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// do stuff
}
},3000);
Try to make a new Runnable() around the try-catch-block.
Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise.
Source
Register your service in android manifest.
I have an alarm application.
Flow looks like this :
WakefulBroadcastReceiver(Acquires wakelock) --->> Intent service -->> startActivity
public class AlarmService extends IntentService {
protected void onHandleIntent(Intent intent) {
Intent activityIntent = new Intent(this, TriggeredActivity.class);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
Basically WakefulBroadcaseReceiver starts an intent service using startWakefulService(). Inside intent service's onHandleIntent(), only work I am doing is further starting a new activity using startActivity(). That new activity is where I am using mediaPlayer in a loop, which sounds the alarm. That activity has a dismiss button, which waits for user click to stop the media player & activity finishes.
Now the problem I am facing is that after calling startactivity() inside intent service, I can not wait for TriggeredActivity to finish(no equivalent to startActivityForResult in Service) and then complete wakeful intent. Related link
startActivity(activityIntent);
WakefulBCastReceiver.completeWakefulIntent(intent); /* can't do here */
So I am not explicitly releasing wakelock here.
My question is will the wakelock be released automatically(link-to-death), when the process that is holding it is killed.
If yes, then in my particular scenario, I need not call WakefulBCastReceiver.completeWakefulIntent().
Yes, you need to use completeWakefulIntent.
You need to put your TriggeredActivity intent into EXTRAs.
#Override
public void onReceive(Context context, Intent intent) {
Intent intentService = new Intent(context, NotificationsIntentService.class);
// Inserting data inside the Intent
intentService.putExtra(NotificationsIntentService.EXTRA_NOTIF, new Intent(context, TriggeredActivity.class));
startWakefulService(context, intentService);
}
NotificationsIntentService.class
public class NotificationsIntentService extends IntentService {
private static final String TAG = "DebugNotifIntent";
public static final String EXTRA_NOTIF = "extra_notif";
public NotificationsIntentService(){
super(NotificationsIntentService.class.getSimpleName());
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent: ");
Intent extraIntent = intent.getParcelableExtra(EXTRA_NOTIF);
extraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(extraIntent);
NotificationWakefulBroadcastReceiver.completeWakefulIntent(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
I have managed to find a solution for my problem. I am now using a Messenger for message based cross process communication between intent service & triggered activity.
I am passing a handler - alarmServiceHandler, from intent service to activity through a messenger.
Handler alarmServiceHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
if(msg.arg1 == 1) {
completedTriggeredActivity = true;
}
}
};
Inside onHandleIntent(), I am passing handler through Messenger object in intent's extra data.
Messenger alarmServiceMessenger = new Messenger(alarmServiceHandler);
Intent activityIntent = new Intent(this, TriggeredActivity.class);
activityIntent.putExtra("AlarmServiceMessenger", alarmServiceMessenger);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
while(!completedTriggeredActivity){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
WakefulBCastReceiver.completeWakefulIntent(intent);
In TriggeredActivity, I am retrieving messenger in Dismiss button's OnClickListener, just before calling finish() on the activity. And sending back a message to AlarmService with arg = 1, implying end of processing in triggered activity.
buttonDismiss.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Messenger alarmServiceMessenger = getIntent().getParcelableExtra("AlarmServiceMessenger");
Message alarmServiceMessage = Message.obtain();
alarmServiceMessage.arg1 = 1;
try {
alarmServiceMessenger.send(alarmServiceMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
finish();
}
After starting triggered activity, I am putting AlarmService in sleep mode till boolean variable completedTriggeredActivity has not been set to true in handleMessage(). Once true, it means triggered activity has finished & now I can proceed with releasing wake lock.
I would be glad to receive comments about my approach & any suggestions towards a better solution to my problem, than the one I have deviced.
I have a BroadCastRecevier that works in an asnyc task and it works when server sent a message then broadcast sends this server messages to activities. When activity get the message I am doing some process using a Handler However sometimes handler is not triggered. I mean broadcast sends three messages but handler works two times.
g.broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
srvrMessage = intent.getStringExtra("message");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
myHandler.sendEmptyMessage(1);
}
};
To avoid this issue I decide to use a Service. I have created a service class and want that handler work inside of it but I could not send myHandler as a parameter while starting the service. How can I make this handler works in the service?
I think these links will help you:-
http://techblogon.com/android-service-example-code-description-complete-tutorial/
http://blog.denevell.org/android-service-handler-tutorial.html
In my android app i have one service which calls some webservices after a fix interval.
App is running perfectly in foreground and refresh data,but when user exit from app and use some other app then my app force close after many times.
Why this app force close while running in background.
Code that i was using for start service -
msgIntent = new Intent(mContext, MyBackgroundService.class);
startService(msgIntent);
and inside onDestroy() of my main activity i have following code to stop service-
if(msgIntent!=null){
stopService(msgIntent);
}
background service call some async task and each aync task onPostExecute() method execute some insert statement in database.
i am not geting why this force close occure.
Please give your comments.
Thanks in advance.
My Service Code
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
callAsynchronousTask();
return Service.START_NOT_STICKY;
}
#Override
public void onCreate() {
mContext = this;
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void callAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
callWebservice();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
timer.schedule(doAsynchronousTask, START_DELAY, DELAY);
}
Actually the problem is here
if(msgIntent!=null){
stopService(msgIntent);
}
in your onDestroy(). Because when you close your application so this above code gets called which is closing your service.
And after closing service again you are trying to insert data by calling service + web service. Hence, there is no service object thats why it gets crashed.
To handle this scenario, you need to comment above code which is in onDestroy() & then check/run it, will solve your problem. & there you need to stop your service by other ways. Go step by step.
you stop the service at onDestroy() method. but services are not depend the activity. So try to neglect the stop service.
(or)
try
{
//stop service code
}
catch(Exception e)
{
}
try this.
I am building an app which requires a connection to an MQTT server. Everything works fine, but I want to make it fail proof. More specifically, I need that when the service is unable to connect to the MQTT server, the application closes as it can't do anything. I tried to broadcast an intent to the activity, but the broadcast doesn't reach it after catching the exception. (I ommited some code for easier understanding)
Service's onHandleIntent()
try{
mqttClient.connect();
} catch (MqttException e) {
Intent msgint = new Intent();
msgint.setAction(constantStrings.SH_CONN_ERROR);
sendBroadcast(msgint);
Log.d("MqttLog","ERROR-MqttException " + e.getMessage());
}
The Activity I need to finish (SelectionGrid.class)
#Override
protected void onCreate(Bundle savedInstanceState) {
[...]
IntentFilter filter = new IntentFilter();
filter.addAction(constantStrings.SH_CONNERROR);
registerReceiver(SH_Communication, filter);
}
BroadcastReceiver SH_Communication = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(constantStrings.SH_CONN_ERROR)){
new AlertDialog.Builder(getApplicationContext())
.setTitle("Error")
.setMessage("No conection")
.setCancelable(false)
.setPositiveButton("Close app", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
SelectionGrid.this.finish();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
};
I do get the Log entry when catching the exception, but the broadcast never gets to the activity.
Is there any better way to do this?
I was able to solve it. It turned out that I was calling the wrong activity which looks a lot like the one I really needed. The code that I showed in the question is correct.