I'm making a Service that creats a thread in the Oncreate methed. this thread is a endless loop thAT PLAYS A MP3 FILE, GOES TO SLEEP FOR 30 SECONDS.
i'M TRYING TO FIGURE OUT HOW TO stop this in the onDestroy methed
code
public void onCreate() {
Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
mediaPlayer = MediaPlayer.create(this, R.raw.nysound);
mThread=new myThread();
mThread.start();
}
public class myThread extends Thread {
public void run() {
do{
mediaPlayer.start();
try
{
Thread.sleep(1000*20);
} catch(Exception e)
{
ted++;
}
} while(true);
} // end methed
} // end class
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
You could use a boolean flag for that
public class myThread extends Thread {
private volatile boolean running = true;
public void run() {
do{
mediaPlayer.start();
try
{
Thread.sleep(1000*20);
} catch(Exception e)
{
ted++;
}
} while(running);
} // end methed
public void setRunning(boolean newValue) {
this.running = newValue;
}
} //
And then do the following in main thread
#Override
public void onDestroy() {
mThread.setRunning(false);
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
Calling onDestroy() is not the right way to stop Service
public void onDestroy () is called by the system to notify a Service that it is no longer used and is being removed. The service should clean up any resources it holds (threads, registered receivers, etc) at this point. Upon return, there will be no more calls in to this Service object and it is effectively dead. Do not call this method directly.
if you are in service class please call method
stopSelf();
if you are in another class, like your MusicPlayerActivity call below code
Intent i = new Intent(this, ServiceName.class);
stopService(i);
Both of these will stop your service.
You should consider using higer-level object ScheduledExecutorService to handle thread execution :
public void onCreate() { Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
mediaPlayer = MediaPlayer.create(this, R.raw.nysound);
ScheduledExecutorService ses =
Executors.newScheduledThreadPool(1);
scheduledFuture = ses.scheduleWithFixedDelay(new MyThread(), 0, 20, TimeUnit.SECONDS);
}
public class myThread extends Thread {
public void run() {
mediaPlayer.start();
} // end methed
} // end class
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
scheduledFuture.cancel(true);
}
Related
Please guide me in this. Appreciate all your help.
My background service is toasting ABC
//-------------------String displayingText = "ABC";-----------------
And I have two strings, ABC and DEF declared in mainactivity.java
How do I pass the value displayingText from main activity to this service.
How do I change the displayingText to DEF after the toast ABC finished.
MyService.Java
public class MyService extends Service {
public static final long INTERVAL=3000;//variable to execute services every 5 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
//the get intent dont work. where or how should i put it?
Intent myIntent = getIntent();
if (myIntent !=null && myIntent.getExtras()!=null)
String value = myIntent.getExtras().getString(PassToService);
#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 onTaskRemoved(Intent rootIntent) {
stopSelf();///its will stop service
super.onTaskRemoved(rootIntent);
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
super.onDestroy();
}
//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
//String displayingText = "ABC";
String displayingText = myIntent.getStringExtra("PassToService");
final Toast Notify = Toast.makeText(getApplicationContext(), displayingText, Toast.LENGTH_SHORT);
Notify.setGravity(Gravity.CENTER, 0, 0);
Notify.show();
Handler cancelToast = new Handler();
cancelToast.postDelayed(new Runnable() {
#Override
public void run() {
Notify.cancel();
}
}, 1000);
}
});
}
}
}
You can do it by passing value from activity to service-
startService(new Intent(YourActivity.Service.class).putExtra("key","value"));
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>
I am trying to show a toast at 2 seconds interval from a service.
This normal code works fine. This one is just a test to show toast.
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
new Thread(new ToastRunner(this)).start();
return START_STICKY;
}
But the below code crashes...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
new Thread(new ToastRunner(this)).start();
return START_STICKY;
}
class ToastRunner implements Runnable{
Context context;
public ToastRunner(Context context){
this.context = context;
}
#Override
public void run() {
try {
while (true) {
Toast.makeText(context, "Service Started", Toast.LENGTH_SHORT).show();
Thread.sleep(2000);
}
}catch (Exception e){
Log.d("tag", e.toString() );
}
}
}
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Try this code,
while (true) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Service Started", Toast.LENGTH_SHORT).show();
}
});
Thread.sleep(2000);
}
That mean you cannot access ui element from one another thread. You must use uiThred. Try this code,
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Service Started", Toast.LENGTH_SHORT).show();
Thread.sleep(2000);
}
}
}
try like this...
#Override
public void run() {
try {
// preparing a looper on current thread
// the current thread is being detected implicitly
Looper.prepare();
// now, the handler will automatically bind to the
// Looper that is attached to the current thread
// You don't need to specify the Looper explicitly
handler = new Handler();
// After the following line the thread will start
// running the message loop and will not normally
// exit the loop unless a problem happens or you
// quit() the looper (see below)
Looper.loop();
}
catch (Throwable t) {
Log.e(TAG, "halted due to an error", t);
}
}
I have this code:
if (value) {
thread = new Thread() {
#Override
public void run() {
try {
while (!isConnected()) {
synchronized (this) {
wait(3000);
}
}
} catch (InterruptedException ex) {
}
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
};
thread.start();
}
I want my app to wait until google api client is connected and than send a message.
The code for the isConnected method is:
public boolean isConnected() {
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) {
return true;
}
return false;
}
But I get this error message:
NullPointerException: Can't create handler inside thread that has not called Looper.prepare(), and it says that the mistake is somewhere id showWifiSettingsAlert()
here is the code:
public void showWifiSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
// Setting Dialog Title
alertDialog.setTitle("Location accuracy tips");
// Setting Dialog Message
alertDialog
.setMessage("You can improve the accuracy of your location by turning on\n- Wi-Fi");
// On pressing Settings button
alertDialog.setPositiveButton("Turn on",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
wifiManager.setWifiEnabled(true);
// Posalji poruke al pre toga jos jednom azuriraj
// lokaciju al ako je pozvana aplikacija iz widgeta
if (value) {
sendMessageWidget();
}
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
wifiManager.setWifiEnabled(false);
// Posalji poruke al pre toga jos jednom azuriraj
// lokaciju al ako je pozvana aplikacija iz widgeta
if (value) {
sendMessageWidget();
}
}
});
// Showing Alert Message
alertDialog.show();
}
I want, if wifi is not enabled, the user to choose to enable it or not, but either way the message should be sent... can you help please?
Since you can't touch the UI from a thread other than the main thread, you must post these changes back to the UI thread and its looper and associated handlers. You can do so explicitly by creating a handler associated with the UI thread (which will work anywhere, since Looper.getMainLooper() is a static call) such as:
if (value) {
Handler uiCallback = new Handler(Looper.getMainLooper());
thread = new Thread() {
#Override
public void run() {
try {
while (!isConnected()) {
synchronized (this) {
wait(3000);
}
}
} catch (InterruptedException ex) {
}
uiCallback.post(new Runnable() {
#Override public void run() {
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
});
}
};
thread.start();
}
Or instead of using a handler at all, you can wrap the part in the run() method in runOnUiThread() if you are in an activity which does the same thing.
You should note however, you don't actually need to use any threading here. If you follow the example on: https://developer.android.com/google/auth/api-client.html you'll find that by implementing ConnectionCallbacks, OnConnectionFailedListener you can call mGoogleApis.connect() from the activity's onStart() and when it connects or fails to do the corresponding callback will be executed on the calling thread. For instance,
#Override
public void onConnected(Bundle connectionHint) {
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
Achieves the same thing...
You are using mGoogleApiClient.connect();, which is an asynchronous method, in a thread and this isn't allowed.
You could try using runOnUiThread instead :
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//do your stuff here
}
});
I'm having trouble STOPPING the StimulationService , I'm not sure if i'm calling the stopservice method correctly from my activity.
Any help will be much appreciated.
Activity to start and stop Service
public class Stimulation extends Activity implements OnClickListener {
private static final String TAG = "StimulationActivity";
Button buttonStart, buttonStop;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.someapp.Activities.R.layout.stimulation);
buttonStart = (Button) findViewById(com.someapp.Activities.R.id.ButtonStart);
buttonStop = (Button) findViewById(com.someapp.Activities.R.id.ButtonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case com.someapp.Activities.R.id.ButtonStart:
Log.d(TAG, "onClick: starting service");
startService(new Intent(this, StimulationService.class));
break;
case com.someapp.Activities.R.id.ButtonStop:
Log.d(TAG, "onClick: stopping service");
stopService(new Intent(this, StimulationService.class));
break;
}
}
}
}
Service
public class StimulationService extends Service {
private static final String TAG = "StimulationService";
private IOIO ioio_;
private DigitalOutput led
private volatile IOIOThread ioio_thread_;
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
ioio_thread_.stop();
}
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
ioio_thread_ = new IOIOThread();
ioio_thread_.start();
}
public void onStop(Intent intent, int stopid) {
Log.d(TAG, "stop()");
ioio_thread_ = null;
}
class IOIOThread extends Thread {
private IOIO ioio_;
private DigitalOutput led;
/** Thread body. */
public void run() {
Thread thisThread = Thread.currentThread();
super.run();
while (ioio_thread_ == thisThread) {
ioio_ = IOIOFactory.create();
try{
Log.d(TAG, "Wait for IOIO Connection");
ioio_.waitForConnect();
Log.d(TAG, "IOIOConnected");
while (true) {
intializePins();
Log.d(TAG, "Pins Intialized");
while(true){
led.write(false);
sleep(2000);
led.write(true);
sleep(2000);
}
}
}
catch (ConnectionLostException e) {
} catch (Exception e) {
Log.e("Hello", "Unexpected exception caught", e);
ioio_.disconnect();
break;
} finally {
try {
ioio_.waitForDisconnect();
} catch (InterruptedException e) {
}
}
}
}
}
First, as #Waqas notes, there is no onStop() method. There is an onDestroy() method, which will be called after stopService() is called.
Second, you are not stopping the background thread ever. Simply setting the ioio_thread_ data member to null does not stop the thread. That thread will keep running forever. Please do not do this. If nothing else, use an AtomicBoolean instead of a hardwired true in your while() loop, and flip that AtomicBoolean to false in onDestroy().
Your activity is OK. The problem is that the service is not killing the IOIOThread.
Thread.stop() is deprecated and will not do what you want anyway.
What you want is to call ioio_.disconnect() from the service's onStop() (through a method on your thread class), and then join() the thread.
See AbstracIOIOActivity as an example. With minor modifications it can be turned into AbstractIOIOService, and will enable you to leave you application-specific logic in a subclass.