i was wondering if the IntentService has thread blocking limit like calling Thread.sleep(); and if so what's the maximum time limit for it?
so i wrote the following code snippet:
package net.yassin.aaaservice;
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.SystemClock;
import android.widget.Toast;
public class MyService extends IntentService {
private Thread t;
private static int i = 0;
private static final int SLEEP_DURATION = 2000;
private Handler handler;
public MyService() {
super("MyService");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
this.handler = new Handler();
}
#Override
protected void onHandleIntent(Intent arg0) {
this.t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
MyService.this.handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyService.this,
"This is toast #" + (++i),
Toast.LENGTH_SHORT).show();
}
});
try {
Thread.sleep(SLEEP_DURATION);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
this.t.start();
}
}
and i found that whenever i change the time SLEEP_DURATION constant to over than 2000 Milis the service will stop showing Toasts if i removed the app form the recent menu?
am i right or there is another time limit or behavior ?
thnx :)
Related
My Android application has a service, that will be created at timer task with specified interval. The task should check out webservice by async task, if the Internet is enabled, send some informations, otherwise it should wait (for example, 5 seconds) and check connection again.
My problem is: how to prevent creating tasks while timertask is waiting?
I wish that at any time there is only one task working.
My code:
mTimer.scheduleAtFixedRate(new MyTask(), 0, 10000); //creating tasks in service
class MyTask extends TimerTask {
#Override
public void run() {
if (!isLocked) {
new Thread(new Runnable() {#Override
public void run() {
isLocked = true;
if (!isInternet) {
do {
Log.v("TestService", "Waiting...");
SystemClock.sleep(5000);
isInternet = getInternetConn();
} while (!isInternet);
} else {
//do work
}
isLocked = false;
}).run();
}
}
}
I would suggest you to follow this process, which i have used for getting GCM_Registration id, same as you can use it check your internet connection.
which works like : in onStartCommand(), mServiceHandler.sendMessage(msg); starts a asynctask which check does we have GCM-ID if yes we stop the service and if no, then we again check for GCM-ID by asynctask.
package com.urbanft.utils;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.text.TextUtils;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.urbanft.app.GlobalPreference;
public class GCMIdFetchService extends Service {
private final String SENDER_ID = "916449540455";
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private static final long INTERVAL = 1000;
private GoogleCloudMessaging mGoogleCloudMessaging;
private String mRegisterationId;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg){
new GCMIdFetchSearviceTask().execute("");
}
}
protected void initialization() {
mGoogleCloudMessaging = GoogleCloudMessaging.getInstance(getApplicationContext());
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
}
class GCMIdFetchSearviceTask extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params) {
getGCMID();
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
String gcmId = GlobalPreference.getInstance(getApplicationContext()).getGCMRegistrationId();
if(!TextUtils.isEmpty(gcmId)){
stopSelf();
return;
}
new Handler().postDelayed(new Runnable() {
public void run() {
Message msg = mServiceHandler.obtainMessage();
mServiceHandler.sendMessage(msg);
}
}, INTERVAL);
}
}
private void getGCMID() {
try{
if(mGoogleCloudMessaging == null){
mGoogleCloudMessaging = GoogleCloudMessaging.getInstance(getApplicationContext());
}
mRegisterationId = mGoogleCloudMessaging.register(SENDER_ID);
GlobalPreference.getInstance(getApplicationContext()).setGCMRegistrationId(mRegisterationId);
}
catch (IOException err){
err.printStackTrace();
}
}
}
I have an android application and I want to show a notification or toast every 10 seconds for example from Service when application is closed or finished
I have provided below a sample activity, a service class and a Timer class. use similar implementation in your application.
Activity Class
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
public class Sample extends Activity {
Button button1,button2;
private Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Call the start and stop method when needed.
}
public void Start(View v)
{
startService(new Intent(MainActivity.this , Sample_service.class));
}
public void Stop(View v)
{
stopService(new Intent(MainActivity.this , Sample_service.class));
}
}
Service Class
package com.example.connect;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class Sample_service extends Service{
Timer timer = new Timer();
TimerTask updateProfile = new CustomTimerTask(Sample_service.this);
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(updateProfile, 0, 10000);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
timer.cancel();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Timer class
package com.example.connect;
import java.util.TimerTask;
import android.content.Context;
import android.os.Handler;
import android.widget.Toast;
public class CustomTimerTask extends TimerTask {
private Context context;
private Handler mHandler = new Handler();
public CustomTimerTask(Context con) {
this.context = con;
}
#Override
public void run() {
new Thread(new Runnable() {
public void run() {
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(context, "DISPLAY YOUR MESSAGE", Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
}
I have given here three files,MainActivity,Manifest and MyService file implement it in your application and it will display toast service at every 10 seconds.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//load the layout file
startService(new Intent(this,MyService.class));//use to start the services
}
}
MyService.java
public class MyService extends Service {
public static final long INTERVAL=10000;//variable to execute services every 10 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
#Nullable
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("unsupported Operation");
}
#Override
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
}
//inner class of TimeDisplayTimerTask
private class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast at every 10 second
Toast.makeText(getApplicationContext(), "Notify", Toast.LENGTH_SHORT).show();
}
});
}
}
}
AndroidManifest.xml
<service android:name=".MyService"
android:enabled="true"/>
Technically, When task is executed which you wrote in onCreate() method, It automatically close. For this you can use timer/scheduler.
Example :
Timer timer;
TimerTask timerTask;
timer.schedule(timerTask, 5000, 10000);
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
Toast toast = Toast.makeText(getApplicationContext(), strDate, duration);
toast.show();
}
});
}
};
Don't forget to add your service in the manifest file inside the application Tag :
<service android:name=".ServiceGPS"
android:permission="[Add permission here if exists]"
android:label="[service name]" android:exported="true"
android:enabled="true">
</service>
I'm making game in OpenGL 2.0 and I have problems with sounds, because sounds slow down my application and FPS decrease about 20 frames. I implement service for sounds and run it on new thread, but problem is same. MediaServer use more CPU than my application with lot of sprites.
I play only three sounds with total size less than 0.5 MB.
This is my code:
package com.filsoft.mouse;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
public class Sound extends Service implements OnCompletionListener {
private final IBinder mBinder = new LocalBinder();
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
MediaPlayer[] mediaPlayer=new MediaPlayer[3];
public ServiceHandler(Looper looper) {
super(looper);
mediaPlayer[0] = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
mediaPlayer[0].setLooping(true);
mediaPlayer[1] = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
mediaPlayer[1].setLooping(true);
mediaPlayer[2] = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
mediaPlayer[2].setLooping(true);
try {
for(int i=0;i<3;i++)
mediaPlayer[i].prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void handleMessage(Message msg) {
play(msg.arg1);
}
public void stopAll()
{
if (mediaPlayer[0].isPlaying()) {
mediaPlayer[0].pause();
}
if (mediaPlayer[1].isPlaying()) {
mediaPlayer[1].pause();
}
if (mediaPlayer[2].isPlaying()) {
mediaPlayer[2].pause();
}
}
public void play(int idx)
{
stopAll();
if (!mediaPlayer[idx].isPlaying()) {
mediaPlayer[idx].start();
}
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("Audio",
Process.THREAD_PRIORITY_URGENT_AUDIO);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
public void startPlay(int idx)
{
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = idx;
mServiceHandler.sendMessage(msg);
}
public class LocalBinder extends Binder {
public Sound getService() {
return Sound.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void onDestroy() {
}
public void onCompletion(MediaPlayer _mediaPlayer) {
stopSelf();
}
}
Instead of creating multiple MediaPlayers, you should use a SoundPool - a class specifically designed to play multiple streams simultaneously such as found in games. Looping sounds is also very easy:
Sounds can be looped by setting a non-zero loop value. A value of -1 causes the sound to loop forever. In this case, the application must explicitly call the stop() function to stop the sound. Any other non-zero value will cause the sound to repeat the specified number of times, e.g. a value of 3 causes the sound to play a total of 4 times.
I want to display toast message inside timer and I used the following code :
timer.scheduleAtFixedRate( new TimerTask()
{
public void run()
{
try {
fun1();
} catch (Exception e) {e.printStackTrace(); }
}
}, 0,60000);
public void fun1()
{
//want to display toast
}
And I am getting following error:
WARN/System.err(593): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
WARN/System.err(593): at android.os.Handler.(Handler.java:121)
WARN/System.err(593): at android.widget.Toast.(Toast.java:68)
WARN/System.err(593): at android.widget.Toast.makeText(Toast.java:231)
Thanks.
You can't make UI updates inside separate Thread, like Timer. You should use Handler object for UI update:
timer.scheduleAtFixedRate( new TimerTask() {
private Handler updateUI = new Handler(){
#Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
fun1();
}
};
public void run() {
try {
updateUI.sendEmptyMessage(0);
} catch (Exception e) {e.printStackTrace(); }
}
}, 0,60000);
The easiest way (IMO) is:
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
final String message = "Hi";
MyActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MyActivity.this, message, Toast.LENGTH_SHORT).show();
}
});
}
});
The key being MyActivity.this.runOnUiThread(Runnable).
create a Handler and display toast in this
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// Toast here
}
};
You need access to the Context of the application to be able to do this. Try creating your own class which takes the context as input parameter:
private class MyTimerTask extends TimerTask {
private Context context;
public MyTimerTask(Context context) {
this.context = context;
}
#Override
public void run() {
Toast.makeText(context, "Toast text", Toast.LENGTH_SHORT).show();
}
}
Then in your timer:
timer.scheduleAtFixedRate( new MyTimerTask(this), 0,60000);
I wanted to make a simple project that could display a Toast in a Timer.
The Timer would be started using a service. Then, the Timer starts when the service is started and stops when service is stopped.
Class 1
package com.example.connect;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
Button button1,button2;
private Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1=(Button)findViewById(R.id.button1);
button2=(Button)findViewById(R.id.button2);
}
public void Start(View v)
{
startService(new Intent(MainActivity.this , Connect_service.class));
}
public void Stop(View v)
{
stopService(new Intent(MainActivity.this , Connect_service.class));
}
}
Class 2
package com.example.connect;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class Connect_service extends Service{
Timer timer = new Timer();
TimerTask updateProfile = new CustomTimerTask(Connect_service.this);
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(updateProfile, 0, 5000);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
timer.cancel();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Class 3
package com.example.connect;
import java.util.TimerTask;
import android.content.Context;
import android.os.Handler;
import android.widget.Toast;
public class CustomTimerTask extends TimerTask {
private Context context;
private Handler mHandler = new Handler();
public CustomTimerTask(Context con) {
this.context = con;
}
#Override
public void run() {
new Thread(new Runnable() {
public void run() {
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(context, "In Timer", Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
}
I'm trying to make my own toast with my own views.
I've successfully combined your approaches. The following code allows me to show toasts and change/remove views without crashing, just change the parameters of the MyTimerTask constructor to whatever you need to work on.
public void yourFunction(){
Timer timer = new Timer();
MyTimerTask mtc = new MyTimerTask(this.getContext(), tvNotice);
timer.schedule(mtc, 1000);
}
private class MyTimerTask extends TimerTask {
private TextView tv;
private Context context;
public MyTimerTask(Context pContext, TextView pTv) {
this.tv = pTv;
this.context = pContext;
}
#Override
public void run() {
updateUI.sendEmptyMessage(0);
}
private Handler updateUI = new Handler(){
#Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
tv.setText("TextView Message");
Toast.makeText(context, "Toast Message", 0).show();
}
};
}
You have to call UIThread for showing Toast, not from timer thread.
Else call UI thread from that timer thread.
This link will help you,
http://developer.android.com/resources/articles/timed-ui-updates.html
and this
http://developer.android.com/guide/appendix/faq/commontasks.html#threading
I want to know if it is possible to call an activity through background service in android like :
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
public class background extends Service{
private int timer1;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
SharedPreferences preferences = getSharedPreferences("SaveTime", MODE_PRIVATE);
timer1 = preferences.getInt("time", 0);
startservice();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private void startservice() {
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run() {
mediaPlayerPlay.sendEmptyMessage(0);
}
}, timer1*60*1000);
}
private Handler mediaPlayerPlay = new Handler(){
#Override
public void handleMessage(Message msg) {
try
{
getApplication();
MediaPlayer mp = new MediaPlayer();
mp = MediaPlayer.create(background.this, R.raw.alarm);
mp.start();
}
catch(Exception e)
{
e.printStackTrace();
}
super.handleMessage(msg);
}
};
/*
* (non-Javadoc)
*
* #see android.app.Service#onDestroy()
*/
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
i want to call my activity......
You can call an Activity while onStart() of your service.....
Snippet might be as follows:
#Override
public void onStart(Intent intent, int startId) {
...
Log.i("Service", "onStart() is called");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(<Set your package name and class name here>);
startActivity(callIntent);
...
}
I believe launching user-interactive Activity from a non-interactive Service goes against the design of Android, in that it would pull out control from under the user.
Notifications are the mechanism intended to get user's attention from a background app, and give them an opportunity to launch the interactive Activity.