I want to instantiate a thread in a Service that will work even when the client leaves the app. On his return the Tread will not be instantiated again only certain parameters of it may be changed. So I need to be able to access it. It also concerns rotation of the screen.
The current code starts another thread which is obviously not a desired solution. The commented out stuff shows different approaches but they didn't work either. I will have to access threadService object in main activity as well.
public class MainActivity extends ActionBarActivity {
private static ThreadService threadService;
private ServiceConnection threadConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
ThreadServiceBinder binder = (ThreadServiceBinder) service;
threadService = binder.getService();
}
#Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, ThreadService.class);
this.startService(intent);
/* if(threadConnection == null) {
Intent intent = new Intent(this, ThreadService.class);
this.startService(intent);
Toast.makeText(this, "Thread service is null", Toast.LENGTH_SHORT).show();
} else {
if(!threadService.ifThreadIsRunning()) {
Intent intent = new Intent(this, ThreadService.class);
this.startService(intent);
Toast.makeText(this, "Thread service is not null", Toast.LENGTH_SHORT).show();
}
}*/
}
#Override
public void onDestroy() {
this.stopService(new Intent(this, ThreadService.class));
super.onDestroy();
}
/*
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}*/
}
Here is the service
public class ThreadService extends Service {
private final IBinder threadServiceBinder = new ThreadServiceBinder();
public class ThreadServiceBinder extends Binder {
ThreadService getService() {
return ThreadService.this;
}
}
final Handler handler = new Handler();
private BackgroundThread backgroundThread;
public ThreadService() {
/*
* if(backgroundThread == null) backgroundThread =new
* BackgroundThread(handler);
*/
backgroundThread = BackgroundThread.getInstance();
backgroundThread.setHandler(handler);
handler.removeCallbacks(backgroundThread);
handler.postDelayed(backgroundThread, 10000);
}
#Override
public IBinder onBind(Intent intent) {
return threadServiceBinder;
}
public boolean ifThreadIsRunning() {
if (backgroundThread.isAlive()) {
return true;
} else {
return false;
}
}
}
class BackgroundThread extends Thread {
private static BackgroundThread instance;
private Handler mHandler;
private BackgroundThread() {
}
public static synchronized BackgroundThread getInstance() {
if (instance == null) {
instance = new BackgroundThread();
}
return instance;
}
public void setHandler(Handler handler) {
if (mHandler == null) {
mHandler = handler;
}
}
/*
* public BackgroundThread(Handler handler) { super(); mHandler = handler; }
*/
#Override
public void run() {
try {
Log.d("com.example.timer", "We are in Runnable run try section");
mHandler.postDelayed(this, 10000);
} catch (Exception e) {
// TODO: handle exception
}
/*
* finally{ handler.postDelayed(runable, 2000); }
*/
}
}
Related
I'm using an implementation of android.media.projection.MediaProjection to get images and it is working just fine. However when calling myService.myRunnable.run() from MainActivity, the callback onImageAvailable() stop getting called. Where myService is a Foreground Service bound to the activity, and myRunnable a Runnable object member of myService.
public class MainActivity extends Activity {
private MyService myService;
ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
isServiceBounded = false;
myService = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
isServiceBounded = true;
MyService.LocalBinder mLocalBinder = (MyService.LocalBinder) service;
myService = mLocalBinder.getServerInstance();
}
};
public class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
#Override
public void onImageAvailable(ImageReader reader) {
Log.d(TAG, "this is called for each new frame until the button is pressed");
...
}
#Override
protected void onCreate(Bundle savedInstanceState) {
button.setOnClickListener(views -> {
myService.myRunnable.run()
});
if (!isMyServiceRunning(MyService.class)) {
startMyService();
bindToMyService();
}
}
#Override
protected void onDestroy() {
myService.killMyRunnable();// -> myRunnable = null;
stopMyService();
unbindService(mConnection);
super.onDestroy();
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
...
if (running) ? return true : return false;
}
}
,
public class MyService extends Service {
IBinder mBinder = new LocalBinder();
public MyRunnable myRunnable;
public class LocalBinder extends Binder {
public MyService getServerInstance() {
return MyService.this;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
}
...
}
,
public class MyRunnable implements Runnable {
private void dummyWorkload(){
Log.d(TAG, "dummyWorkload: isWorking");
try {
Thread.sleep(2000);
dummyWorkload();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
dummyWorkload();
}
}
What is causing this issue?
The code stops the MediaProjection because it invokes myRunnable.run() from the MainThread, therefore freezing the UI while the runnable is busy. For the projection to continue working it should be called from a separate Thread. To solve the issue, either extends Thread instead of implements Runnable interface or call the Runnable this way:
Thread myThread = new Thread(new myRunnable);
myThread.start();
I am working on application, where in am getting a tasks from server and then user evaluate through Mobile Application(just like a quiz Application).
During Evaluation of Tasks, if the user presses home button then app goes to background. And when user back to application from recent background applications, then Application started from Splash screen.
I am confused that what price of code should I add, so that when user back to Application, then previous state must be shown to the user??
copy this class further i will tell you what to do
public class Foreground implements Application.ActivityLifecycleCallbacks {
public static final long CHECK_DELAY = 50;
public static final String TAG = Foreground.class.getName();
public interface Listener {
public void onBecameForeground();
public void onBecameBackground();
}
private static Foreground instance;
private boolean foreground = false, paused = true;
private Handler handler = new Handler();
private List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
private Runnable check;
/**
* Its not strictly necessary to use this method - _usually_ invoking
* get with a Context gives us a path to retrieve the Application and
* initialise, but sometimes (e.g. in test harness) the ApplicationContext
* is != the Application, and the docs make no guarantees.
*
* #param application
* #return an initialised Foreground instance
*/
public static Foreground init(Application application){
if (instance == null) {
instance = new Foreground();
application.registerActivityLifecycleCallbacks(instance);
}
return instance;
}
public static Foreground get(Application application){
if (instance == null) {
init(application);
}
return instance;
}
public static Foreground get(Context ctx){
if (instance == null) {
Context appCtx = ctx.getApplicationContext();
if (appCtx instanceof Application) {
init((Application)appCtx);
}
throw new IllegalStateException(
"Foreground is not initialised and " +
"cannot obtain the Application object");
}
return instance;
}
public static Foreground get(){
if (instance == null) {
throw new IllegalStateException(
"Foreground is not initialised - invoke " +
"at least once with parameterised init/get");
}
return instance;
}
public boolean isForeground(){
return foreground;
}
public boolean isBackground(){
return !foreground;
}
public void addListener(Listener listener){
listeners.add(listener);
}
public void removeListener(Listener listener){
listeners.remove(listener);
}
#Override
public void onActivityResumed(Activity activity) {
paused = false;
boolean wasBackground = !foreground;
foreground = true;
if (check != null)
handler.removeCallbacks(check);
if (wasBackground){
Log.i(TAG, "went foreground");
for (Listener l : listeners) {
try {
l.onBecameForeground();
} catch (Exception exc) {
Log.e(TAG, "Listener threw exception!", exc);
}
}
} else {
Log.i(TAG, "still foreground");
}
}
#Override
public void onActivityPaused(Activity activity) {
paused = true;
if (check != null)
handler.removeCallbacks(check);
handler.postDelayed(check = new Runnable(){
#Override
public void run() {
if (foreground && paused) {
foreground = false;
Log.i(TAG, "went background");
for (Listener l : listeners) {
try {
l.onBecameBackground();
} catch (Exception exc) {
Log.e(TAG, "Listener threw exception!", exc);
}
}
} else {
Log.i(TAG, "still foreground");
}
}
}, CHECK_DELAY);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
#Override
public void onActivityStarted(Activity activity) {}
#Override
public void onActivityStopped(Activity activity) {}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
#Override
public void onActivityDestroyed(Activity activity) {}
}
add this in onCreate of year Application Class
Foreground foreground = Foreground.init(this);
final Foreground.Listener myListener = new Foreground.Listener()
{
public void onBecameForeground()
{
Log.d("TAG", "FOREGROUND");
}
public void onBecameBackground()
{
//registerActivityLifecycleCallbacks(new MyLifecycleHandler());
Intent i = new Intent("android.intent.action.MAIN").putExtra("some_msg", "I will be sent!");
sendBroadcast(i);
}
};
foreground.addListener(myListener);
add this code in onCreate of your Base Activity ok ?
IntentFilter intentFilter = new IntentFilter(
"android.intent.action.MAIN");
mReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
//extract our message from intent
String msg_for_me = intent.getStringExtra("some_msg");
//log our message value
Log.i("InchooTutorial", msg_for_me);
finish();
}
};
//registering our receiver
this.registerReceiver(mReceiver, intentFilter);
not this this is your override onDestroy method copy outside the oncreate
#Override
protected void onDestroy()
{
super.onDestroy();
unregisterReceiver(mReceiver);
}
Overide the methods onStop(), onPause(), onResume() in your main activity.
I have spend all day dealing with this problem, I can't solve it. I am exhausted ,have no ideas what to do with it. Please help.
I want to create service that plays music in background.But receiving always null instead of service. Sometimes onServiceConnected is called, sometimes not
public class SoundService extends Service {
private IBinder myBinder = new MyLocalBinder() ;
private static boolean isSoundOn = false;
private static boolean isBgMusicOn = false;
private static int[] soundPoolIds = null;
private Context appContext = null;
private static SoundPlayer instance = null;
private MediaPlayer mp = null;
private SoundPool sndPool = null;
public class MyLocalBinder extends Binder {
public SoundService getService() {
return SoundService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return myBinder;
}
#Override
public void onCreate() {
super.onCreate();
// initSoundPools();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
// TODO Auto-generated method stub
super.onRebind(intent);
}
public long getCurrentTime() {
Time time = new Time();
time.setToNow();
return time.toMillis(false);
}
#SuppressLint("NewApi")
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
private void initBackground() {
//Some magic code here
}
private void playMusic(MediaPlayer mp) {
//Some magic code here
}
private boolean musicIsPlaying(MediaPlayer mp) {
//Some magic code here
}
return false;
}
public void stopPlayingBackground() {
//Some magic code here
}
private void stopPlaying(MediaPlayer mp,boolean release) {
//Some magic code here
}
private int randInt(int min, int max) {
//Some magic code here
}
private void initSoundPools() {
//Some magic code here
}
public void turnSoundOn(boolean on) {
isSoundOn = on;
}
public void turnMusicOn(boolean on) {
isBgMusicOn = on;
}
public void playBackgroundMusic() {
//Some magic code here
}
public void playSoundFx(int id) {
//Some magic code here
}
}
}
Here is Class that extends another that in turn extends Activity
public class MainActivity extends LGame {
p
private static final String TAG = "DEBUG";
private static SoundService soundService;
private static boolean isBound = false;
private Thread serviceThread;
private ServiceConnection myConnection;
#Override
public void onGamePaused() {
}
#Override
public void onGameResumed() {
// TODO Auto-generated method stub
}
#Override
protected void onDestroy() {
}
if (soundService!=null) {
soundService.stopSelf();
}
super.onDestroy();
}
public static SoundService getSoundService() {
return soundService;
}
#Override
public void onMain() {
LTexture.ALL_LINEAR = true;
LSetting setting = new LSetting();
setting.width = 800;
setting.height = 480;
setting.fps = 30;
setting.landscape = true;
setting.showFPS = false;
myConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
MyLocalBinder binder = (MyLocalBinder) service;
soundService = binder.getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
serviceThread = new Thread(){
public void run(){
Intent intent = new Intent(getApplicationContext(), SoundService.class);
getApplicationContext().bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
}
};
serviceThread.start();
register(setting, MainGame.class);
}
Firstly I tried to start service in main thread but nothing changed in both cases.
Of course I've declared service in manifest.
I hope someone can help me with this.
Thx for help in advance.
EDIT
I have mentioned that I have already tried to start it like in your post but nothing changed
HELP !! I have tried almost everything
You should never bind a service in different thread, if you want to do async tasks you should create the threads inside the service itself.
#Override
public void onMain() {
LTexture.ALL_LINEAR = true;
LSetting setting = new LSetting();
setting.width = 800;
setting.height = 480;
setting.fps = 30;
setting.landscape = true;
setting.showFPS = false;
myConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
MyLocalBinder binder = (MyLocalBinder) service;
soundService = binder.getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
Intent intent = new Intent(getApplicationContext(), SoundService.class);
getApplicationContext().bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
register(setting, MainGame.class);
}
From Android documentation :
The bindService() method returns immediately without a value.
So binding your service in the UI thread will not cause any delaying nor UI freezing.
I have a simple Service
public class UpdateService extends Service {
private int seconds;
final static String MY_ACTION = "MY_ACTION";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
timer.start();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
final CountDownTimer timer = new CountDownTimer(86400000, 1000) {
public void onTick(long millisUntilFinished) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
Intent intent = new Intent();
intent.setAction(MY_ACTION);
sendBroadcast(intent);
}
public void onFinish() { }
};
}
When I close an application service stops working. But showing that the service is running.
What am I doing wrong?
Update
I changed CountDownTimer to Thread, but the problem remained
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
OnStart()
if(!t1.isAlive())
t1.start();
Because CountDown Timer is working only foreground means app is running and not minimized or closed. You have to place a Thread in Service that executing at particular time of you want.
try this :
public class LocalService extends Service
{
private static Timer timer = new Timer();
private Context ctx;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
ctx = this;
startService();
}
private void startService()
{
timer.scheduleAtFixedRate(new mainTask(), 0, 5000);
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this, "Service Stopped ...", Toast.LENGTH_SHORT).show();
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
System.out.println("test");
}
};
}
I have a checked button in my MainActivity. If that button is checked it should start the service but if a user unchecked the button I want to stop the service.
So in uncheck condition I have written this stopService(intentname); but the problem is the service is not stopping. Here is my code snippet:
Service Class
public class SimpleService extends Service
{
String selectedAudioPath = "";
private MyThread myythread;
public Intent intent;
public boolean isRunning = false;
long interval=30000;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
myythread = new MyThread(interval);
}
#Override
public synchronized void onDestroy()
{
super.onDestroy();
if(!isRunning)
{
myythread.interrupt();
myythread.stop();
isRunning = false;
}
}
#Override
public synchronized void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
if(!isRunning)
{
//this.intent = intent;
//System.out.println("the intent is" + intent);
myythread.start();
isRunning = true;
}
}
class MyThread extends Thread
{
long interval;
public MyThread(long interval)
{
this.interval=interval;
}
#Override
public void run()
{
while(isRunning)
{
System.out.println("Service running");
try
{
String myString = intent.getStringExtra("name");
if(myString == null)
Log.d("Service","null");
else
{
Log.d("Service","not null");
if(myString.equalsIgnoreCase("image"))
{
uploadImages();
Thread.sleep(interval);
}
else if(myString.equalsIgnoreCase("audio"))
{
uploadAudio();
Thread.sleep(interval);
}
}
}
catch (InterruptedException e)
{
isRunning = false;
e.printStackTrace();
}
}
}
You can't stop a thread that has a running unstoppable loop like this
while(true)
{
}
To stop that thread, declare a boolean variable and use it in while-loop condition.
public class MyService extends Service {
...
private Thread mythread;
private boolean running;
#Override
public void onDestroy()
{
running = false;
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
running = true;
mythread = new Thread() {
#Override
public void run() {
while(running) {
MY CODE TO RUN;
}
}
};
};
mythread.start();
}
Source: Stopping a thread inside a service
Don't use Threads. Use AsyncTask instead.
public class MyService extends Service {
private AsyncTask<Void,Void,Void> myTask;
#Override
public void onDestroy(){
super.onDestroy();
myTask.cancel(true);
}
#Override
public void onStart(Intent intent, int startid) {
myTask = new AsyncTask<Void,Void,Void>(){
#Override
public void doInBackground(Void aVoid[]){
doYourWorkHere();
}
}
myTask.execute();
}
}