Hello I am building an app where I am using service for locations. That service have to work all the time, so I set that when service goes to onDestroy, then intent is sent to BroadcastReceiver who starts service again, and on that way, my service always works. But I want to stop service when user click on button logout. How to prevent that,when service goes to onDestroy, don't send intent to broadcast(but only when user clicks on logout)?
This is my logout from MainActivity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_log_out) {
if (isNetworkConnected()) {
unsubscribingFromFirebase();
removeTokenAndAccountFromSharedPreferences();
stopService(mServiceIntent);
Log.i("MAIN_ACTIVITY", "Logout!");
Log.d("MAIN_ACTIVITY " , "Internet access ");
}
else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.need_internet), Toast.LENGTH_SHORT).show();
}
}
These are methods onStartCommand, onCreate and onDestroy in location service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("onStartCommand" , "LocationService");
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
isEnded = false;
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
Bugsnag.init(this, BUGSNAG_API_KEY);
buildGoogleApiClient();
Log.d("onCreateService", "onCreateService");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "onDestroy!");
timeWhenServiceDestroyed = DateFormat.getTimeInstance().format(new Date());
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.user_location), MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("onDestroyService", timeWhenServiceDestroyed);
editor.apply();
stopLocationUpdates();
Log.d("onDestroyService", "onDestroy: + " + timeWhenServiceDestroyed);
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
And this is my BroadCastReceiver:
#Override
public void onReceive(Context context, Intent intent) {
Log.i(LocationServiceRestartBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
context.startService(new Intent(context, LocationService.class));
}
How to prevent that when user clicks on logout button, my service don't create again? Thanks in advance.
You could use static boolean variable shouldRestart that is false only when logout button is clicked, otherwise true.
Add to your activity :
public static boolean shouldRestart=true;
Add to your "logout button click event" this line:
shouldRestart=false;
And add this lines in onDestroy method of service :
if (MainActivity.shouldRestart){
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
MainActivity.shouldRestart=true;
Related
I am passing the data from main activity to service.
I am getting these errors in Myservice.java
1. In override oncreate method - method does not override from superclass
2. The displayingText in run - cannot resolve symbol.
Mainactivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//load the layout file
}
String displayingText = "ABC";
public void StartService(View v) {
Intent mIntent = new Intent(this, MyService.class);
startService(mIntent);//(new Intent(this, MyService.class));//use to start the services
mIntent.putExtra("PassToService",displayingText);
Toast.makeText(this, "Started", Toast.LENGTH_SHORT).show();
}
MyService.java
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)//if mTimer is activated
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
public int onStartCommand (Intent intent, int flags, int startId) {
String displayingText = intent.getStringExtra("PassToService");
Toast.makeText(getApplicationContext(), displayingText, Toast.LENGTH_SHORT);
return START_STICKY;
}
You have some problem in your code .
1.change the order of the code
public void StartService(View v) {
Intent mIntent = new Intent(this, MyService.class);
// edited here
mIntent.putExtra("PassToService",displayingText);
startService(mIntent);
Toast.makeText(this, "Started", Toast.LENGTH_SHORT).show();
}
My code
String displayingText = "abc";
public void StartService(View v) {
Intent mIntent = new Intent(this, MyService.class);
startService(mIntent);//(new Intent(this, MyService.class));//use to start the services
mIntent.putExtra("PassToService",displayingText);
Toast.makeText(this, "Started", Toast.LENGTH_SHORT).show();
}
2.register in your manifest for your service
<service android:name=".your_package.MyService"/>
Registered as
<service
android:name=".MyService"
android:enabled="true" />
But the value return nothing.
for StartService(View v)....
you still haven't implemented any action or event in onCreate method.
if you still have can't resove problem, use "Mainactivity.this" in place of this in StartService method.
You can pass data to service like below :-
Intent intent = new Intent(MainActivity.this , GPSTracker.class);
intent.putExtra(YOURKEY , VALUE);
startService(intent);
and you can get your data on onStartCommand() method :-
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null){
intent.getStringExtra(YOURKEY)
}
return START_STICKY;
}
I had done as below. But the toast message return no character(no value)
public int onStartCommand (Intent intent, int flags, int startId) {
String displayingText = intent.getStringExtra("PassToService");
Toast.makeText(this, displayingText, Toast.LENGTH_SHORT).show();
return START_STICKY;
}
You need to use onStartCommand to get the data/values from the activity to service.,
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
after this you can override the oncreate method and display the stuffs.
But you need to remember that ALWAYS ONCREATE METHOD WILL BE EXECUTED WHEN WE USE startservice method in our activity
In Your Activity, just use the below code:
private void initializeService(String Index) {
Intent intent = new Intent(Detail_Test_run.this, Servicelay.class);
intent.putExtra("Index",Index);
startService(intent);
finish();
}
Then in your service use:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
index= intent.getStringExtra("Index");
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
addView(index);
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
}
For me it worked well, where I started calling all my functionalities from onStartCommand() instead of onCreate()
I think you should use sharedpreferances as data wont be available for service in background.
So in your startService() method:
public void StartService(View v) {
Intent mIntent = new Intent(this, MyService.class);
startService(mIntent);
SharedPreferences sp=getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sp.edit();
editor.putString("data",displayingText).commit();
editor.apply();}
And in your service class's onStartCommand() add these lines
SharedPreferences prefs = getSharedPreferences("MyPrefs",MODE_PRIVATE);
String string = prefs.getString("data","");
Hope this helps :)
my Service never stop until I uninstall the app #HELP!
service class
public class LocationService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
GPSTracker myGps = new GPSTracker(getApplicationContext());
Log.e("tracking...","");
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public boolean stopService(Intent name) {
GPSTracker myGps = new GPSTracker(getApplicationContext());
Log.e("STOPPED!","");
return super.stopService(myGps);
}
}
** Start the Service At the Login Activity**
Intent locationService = new Intent(Login.this, LocationService.class);
startService(locationService);
**Stop the service At the employee Activity in option selected menu **
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent serviceIntent;
int id = item.getItemId();
if (id == R.id.LogOut) {
serviceIntent = new Intent(Employee.this, LocationService.class);
stopService(serviceIntent);
Log.e("OUT"," ");
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In the 2 activities A and B u have, you should unbind service in B onStop(), then you can call stopService in A. Simply putting stopService(serviceIntent); might give you and error about leaked service connection
protected ServiceConnection mServerConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(LOG_TAG, "onServiceConnected");
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d(LOG_TAG, "onServiceDisconnected");
}
}
public void start() {
// mContext is defined upper in code, I think it is not necessary to explain what is it
mContext.bindService(i, mServerConn, Context.BIND_AUTO_CREATE);
mContext.startService(i);
}
public void stop() {
mContext.stopService(new Intent(mContext, ServiceRemote.class));
mContext.unbindService(mServerConn);
}
and see in your code what you have done is u have stopped the service but i dont see you unbinding it, the correct procedure would be unbind it then stop it.
Dont use the command startService(service).
To start the service at the beginning of the app just bind it to all your activities. This way, when the activities are destroyed, the service stops.
Explained thoroughly HERE
Also, if you want the service to end when the app is closed(but not destroyed), just add unBindService method to an overrided onStop method.
I am fairly new to android, and I'm trying to pass a value from my activity to my service.
I've seen other answers on this subject but I not find what's my problem, the value does not pass to the service.
In my activity I've a seekbar and I want that when I change the value of seekbar ("progress") and activate the service, the service receives the value. When I close the app the value back to zero, and should be another.
In my activity I save the value with sharePreferences.
Activity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
//SEEKBAR
textViewSensibilidad.setText("Sensibilidad: " + progress*100/seekBar.getMax()+"%");
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progresValue, boolean fromUser) {
progress = progresValue;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
textViewSensibilidad.setText("Sensibilidad: " + progress*100/seekBar.getMax()+"%");
//SAVE STATE SEEKBAR
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("progress", progress);
editor.commit();
}
});
//LOAD STATE SEEKBAR
sharedPreferences = getSharedPreferences("progress" , Context.MODE_PRIVATE);
progress = sharedPreferences.getInt("progress", progress);
seekBar.setProgress(progress);
}
public void onClick(View src) {
if(toggleButton.isChecked()){
Log.d(TAG, "onClick: starting srvice");
Intent intent = new Intent(ShakeActivity.this, MyService.class);
intent.putExtra("progress", progress);
startService(intent);
...
Service
public class MyService extends Service implements SensorEventListener {
private static final String TAG = "Servicio";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
Toast.makeText(this, "Shake to Open Whatsapp Activada", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onStart");
if (intent !=null && intent.getExtras()!=null){
progress = intent.getExtras().getInt("progress");
checkeado=intent.getExtras().getBoolean("checkeado");
Toast.makeText(this, "progreso: "+progress+" checkeado: "+checkeado, Toast.LENGTH_SHORT).show();
}
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Shake to Open Whatsapp Desactivada", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onDestroy");
//player.stop();
mSensorManager.unregisterListener(this);
}
Any suggestions? errors? I thank you in advance
Since you already store the progress value as a shared preference, your service can just get the shared preference value. There is no need to pass it as a value to the service.
In your service register a shared preference listener. Docs here:
http://developer.android.com/reference/android/content/SharedPreferences.html#registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener)
This will allow you to make the service completely independent of the activity yet observe the value changes when they are made.
Example - make your service implement SharedPreferences.OnSharedPreferenceChangeListener interface. Then define the following method in your service:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if ("progress".equals(key) {
int progress = sharedPreferences.getInt("progress", 0);
// we have a new value -> react here
}
}
Finally don't forget to register the listener in the onStartCommand method:
SharedPreferences sharedPrefs = getSharedPreferences("progress", Context.MODE_PRIVATE);
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
How to start same activity again as its created first time. I used INTET to start activity again . but If user press home button at mobile this intent not works . is there anyother way to startactivity as its first created when its in background. Pls help this I shall be very thankful to you for this.
private void sendNextMessage(){
Log.i("Is there are sms sendNextMessage", thereAreSmsToSend()+"");
if(thereAreSmsToSend()){
Log.i("sendNextMessage mMessageSentParts", mMessageSentParts+"");
Log.i("sendNextMessage mMessageSentTotalParts", mMessageSentTotalParts+"");
Log.i("sendNextMessage mMessageSentCount", mMessageSentCount+"");
Log.i("sendNextMessage Phone list", list_phone.get(mMessageSentCount)+"");
sendSMS(list_phone.get(mMessageSentCount),list_MESSAGE_BODY.get(mMessageSentCount));
}else{
Toast.makeText(getBaseContext(), "All SMS have been sent",
Toast.LENGTH_SHORT).show();
new AddNewCategory().execute();
h.removeCallbacks(r);
h.postDelayed(new Runnable() {
public void run() {
// I used this code to start activity again but if user press home button this intent not works .
Intent i = new Intent();
i.setClass(MainActivity.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(i);
Log.e("Time", "60000 intent");
h.removeCallbacks(r);
}
}, 30000);
h.removeCallbacks(r);
h.removeCallbacks(r);
}
}
How about using the SharedPreferences with a boolean value;
Make a class for this:
private Context context;
public boolean saveFirsTime(boolean firstime)
{
SharedPreferences sharedPreferences = getSharedPreferences();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("FirstTime", firstime);
return editor.commit();
}
public boolean loadFirsTime() {
SharedPreferences sharedPreferences = getSharedPreferences();
boolean firstimeMap = sharedPreferences.getBoolean("FirstTime", true);
return firstimeMap;
}
public boolean clearFirsTime() {
SharedPreferences sharedPreferences = getSharedPreferences();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.remove("FirstTime");
return editor.commit();
}
private SharedPreferences getSharedPreferences() {
return context.getSharedPreferences("SharedPrefereneces",Context.MODE_PRIVATE);
}
And then implement saveFirstTime(false) in your Activity onCreate();
Write a service and broadcast receiver something like below :
This Activity start activity on reboot similarly u can write ur event on which activity is called :
public class BootStartUpReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// Start Service On Boot Start Up
Intent service = new Intent(context, TestService.class);
context.startService(service);
//Start App On Boot Start Up
Intent App = new Intent(context, MainActivity.class);
App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(App);
}
}
I have an app that runs a webview as a service so the audio can contiune to play while the screen is locked. The app works great with audio streams such as podcasts. But I also wanted it to work with flash video. I am able to load the flash video stream in the webview and have it play smooth and steady but once the screen goes off or is locked the audio becomes choppy. The behavior is the same on 3g and WiFi. I tried to use this posts suggestion of using a wake lock with:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag");
wl.acquire();
//do what you need to do
wl.release();
However this has no effect. I'm not sure where exactly in my code to put it but I've placed it in the oncreate for the service, which had no effect, and I placed it in the oncreate for my main activity with the same results.
However later in the post the person asking the question said that WIFI_MODE_FULL_HIGH_PERF was able to fix the problem. But as I said I tested it on 3g and the audio stuttered when the screen was turned off.
Any ideas how I can stop this behavior?
Also I know this is a CPU intensive and a battery hog app but I'm just developing it for personal use.
This is my full code for the service:
public class MyService extends Service {
private NotificationManager nm;
private static boolean isRunning = false;
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
int mValue = 0; // Holds last value set by a client.
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_INT_VALUE = 3;
static final int MSG_SET_STRING_VALUE = 4;
PowerManager.WakeLock wl;
#Override
public IBinder onBind(Intent intent) {
wl.acquire();
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("MyService", "Service Started.");
showNotification();
isRunning = true;
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag");
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
notification.flags = Notification.FLAG_ONGOING_EVENT;
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
nm.notify(R.string.service_started, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY; // run until explicitly stopped.
}
public static boolean isRunning()
{
return isRunning;
}
#Override
public void onDestroy() {
super.onDestroy();
nm.cancelAll();
wl.release();
nm.cancel(R.string.service_started); // Cancel the persistent notification.
Log.i("MyService", "Service Stopped.");
isRunning = false;
}
}
My main code:
public class MainActivity extends Activity {
Button btnStart, btnStop, btnBind, btnUnbind, btnUpby1, btnUpby10;
Messenger mService = null;
boolean mIsBound;
WebView mWebView;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
try {
Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT);
mService.send(msg);
} catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been unexpectedly disconnected - process crashed.
mService = null;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnStart = (Button)findViewById(R.id.btnStart);
btnStop = (Button)findViewById(R.id.btnStop);
btnBind = (Button)findViewById(R.id.btnBind);
btnUnbind = (Button)findViewById(R.id.btnUnbind);
btnStart.setOnClickListener(btnStartListener);
btnStop.setOnClickListener(btnStopListener);
btnBind.setOnClickListener(btnBindListener);
CheckIfServiceIsRunning();
//webview
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.loadUrl(url);
mWebView.setWebViewClient(new HelloWebViewClient());
}
private void CheckIfServiceIsRunning() {
//If the service is running when the activity starts, we want to automatically bind to it.
if (MyService.isRunning()) {
doBindService();
}
}
private OnClickListener btnStartListener = new OnClickListener() {
public void onClick(View v){
startService(new Intent(MainActivity.this, MyService.class));
}
};
private OnClickListener btnStopListener = new OnClickListener() {
public void onClick(View v){
doUnbindService();
stopService(new Intent(MainActivity.this, MyService.class));
}
};
private OnClickListener btnBindListener = new OnClickListener() {
public void onClick(View v){
doBindService();
}
};
private OnClickListener btnUnbindListener = new OnClickListener() {
public void onClick(View v){
doUnbindService();
}
};
void doBindService() {
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// If we have received the service, and hence registered with it, then now is the time to unregister.
if (mService != null) {
try {
Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT);
mService.send(msg);
} catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
doUnbindService();
} catch (Throwable t) {
Log.e("MainActivity", "Failed to unbind from the service", t);
}
}
#Override
protected void onResume() {
super.onResume();
}
}
From your description it sounds like you are releasing the WakeLock too soon.
If you are just putting that block of code in the onCreate for the Service then you really aren't getting a WakeLock while your streaming code is running. You must have the lock acquired for the duration of the background work.
The pattern I've used for a service like this is:
Create the WakeLock in onCreate (but do not acquire it)
In onDestroy if the WakeLock is held release it. (mostly for safety)
When starting the actual background work, either in onBind or onStartCommand, acquire the lock.
When done with the background work, release the wake lock.
The problem may be specifically with the way a WebView works. That said since this isn't production code, you could try simply 'leaking' the wake lock by removing the release just to see if that helps. Just create and acquire the lock at the start of your activity and not bother with the Service.
The Service isn't really giving you much. The way your code is currently structured you are still going to have problems. Your Activity can be still deleted when in the background even if you have a Service, simply having a service won't stop this. Further because the WebView is a View it really requires an Activity and view hierarchy.