So i made an app which will run if the power button of the phone pressed 5 time the app will execute something like open url in Background. Now the problem is i want extract latitude and longitude value in that time.
code is
LockService class
public class LockService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
final BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
public class LocalBinder extends Binder {
LockService getService() {
return LockService.this;
}
}
}
ScreenReceiver
public class ScreenReceiver extends BroadcastReceiver {
LocationManager locationManager;
static int countPoweroff =0;
public static boolean wasScreenOn = true;
int lol;
#Override
public void onReceive(final Context context, final Intent intent) {
Log.e("LOB","onReceive");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// do whatever you need to do here
wasScreenOn = false;
countPoweroff++;
Log.e("LOB",""+countPoweroff);
Log.e("LOB","wasScreenOn"+wasScreenOn);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// and do whatever you need to do here
if (countPoweroff == 3){
Log.e("LOB","userpresent");
Log.e("LOB","wasScreenOn"+wasScreenOn);
String url = "http://www.stackoverflow.com";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setData(Uri.parse(url));
context.startActivity(i);
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
//deprecated in API 26
vibrator.vibrate(500);
}
countPoweroff =0;
}
wasScreenOn = true;
}else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
}
}
Run service in main activity
startService(new Intent(getApplicationContext(), LockService.class));
I have used basic Locationmanager code in main activity which works only when the activity open.
Any code that you put in an activity is of course going to be executed only when the activity is running. If your location manager is in activity and the activity is not running, then you can't get location. Your bus won't move anywhere when the driver turned off the engine and went to a lunch break. Doing anything that is unrelated to Ux in an activity is a bad design. I don't know the detail of your implementation, hence, it is difficult to say anything more.You should implement the location manager in a service and send result to the activity using Callable or CompletableFuture.
Related
This is my first question and I've been trying to find a solution to this for hours but can't get it to work. I'm building an android app that takes an input from the user (number of hours) to fast (not eat). The input is then taken to the service where it does a countdown in the background. Along the way, I'd like the user to access other activities that could you the results from the countdown timer (eg, time_left/total_time = percentage complete). So far, my button that I've created works to make the call for the service. but the service never gets called to update the text view. Thanks
Here is what I have,
public class StartFast extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_fast);
startService(new Intent(this, MyService.class));
Log.i("Started service", "hello started service...");
registerReceiver(br, new IntentFilter("COUNTDOWN_UPDATED"));
}
private BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
intent.getExtras();
long millisUntilFinished = intent.getLongExtra("countdown",0);
String time = Long.toString((millisUntilFinished));
TextView tv = findViewById(R.id.timeView1);
tv.setText(time);
}
};
public void BeginFast(View view){
//Intent intent = new Intent( this, StartFast.class);
// below is how to pass an intent for use in a Service to run in the backgroun
Intent intent =new Intent(this, MyService.class);
startService(intent);
// intent.putExtra() // putExtra longs ...will do after static run succeeds
//intent.putExtra("data", data); //adding the data
Intent intent1 = new Intent(this, Heart.class);
startActivity(intent1);
}
}
and here is the service class,
public class MyService extends Service {
private final static String TAG = "MyService";
public static final String COUNTDOWN_BR = "FastBreak.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
public void OnCreate(){
super.onCreate();
Log.i(TAG, "starting timer...");
cdt = new CountDownTimer(30000,1000) {
#Override
public void onTick(long millisUntilFinished){
Log.i(TAG, "Countdown seconds remaining: " +millisUntilFinished /1000);
bi.putExtra("countdown", millisUntilFinished);
sendBroadcast(bi);
}
#Override
public void onFinish(){
Log.i(TAG, "Timer finished");
}
};
cdt.start();
}
#Override
public void onDestroy() {
cdt.cancel();
Log.i(TAG, "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
https://github.com/greenrobot/EventBus
Check this out. This library is the best and easiest implementation of broadcasts. You can send any data to any object (StartFast service in your case) from any other object (StartFast activity in your case) and write code to run.
First, you need to start the service and register it in the manifest. After the service is started by an activity, it will keep running in the background.
You can send intents with a service and anybody who has registered a broadcast receiver listening to that intent can hear it.
Let's say FirstActivity started the service and registers receiver listening to intent with the tag BOBBY. The service is the one sending an intent BOBBY to anyone who is interested and has registered for it.
You want to move on to SecondActivity. Before you do that, onPause of FirstActivity you need to unregister that broadcastreceiver.
SecondActivity is interested in the intent with tag BOBBY, so he creates his own broadcast receiver and registers for it.
I hope you can see where this is going.A broadcastreceiver can listen to all sorts of intents that you make up.
Have fun.
I am aware of the BroadCastReceiver, but how can I use it to call a method in my activity. So if I get a notification from my service, a button in my UI turns red, and red being the object that has been sent from the service and turning red the method that has been called by the activity.
sorry for bad english :)
Register a BroadcastReceiver in your activity
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
if (message.equals("eventOne"))
{
//do something
}
else if (message.equals("eventTwo"))
{
//do something else
}
}
};
Override onResume and onDestroy of your activity
#Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));
}
#Override
protected void onDestroy()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
To check if your service is running add the following on your activity
private static boolean isServiceRunning(String serviceName, Context context)
{
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
if (serviceName.equals(service.service.getClassName()))
{
return true;
}
}
return false;
}
Call it like this
boolean isServiceRunning = isServiceRunning(MyService.class.getName(), this.getApplicationContext());
if (!isServiceRunning)
{
Intent startMyServiceIntent = new Intent(this.getApplicationContext(), MyService.class);
startService(startMyServiceIntent);
}
Finally on your service add a method like that and call it whenever you want
private void sendMessage(String event)
{
Intent intent = new Intent("my-event");
intent.putExtra("message", event);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
sendMessage("eventOne");
return START_STICKY;
}
And don't forget to add your service to manifest
<application
...
...
<service android:name=".MyService"/>
</application>
You can use a BroadcastReceiver, an event bus or an observable. In your activity, listen for the event and call a method that updates your UI how you want.
I do something similarly for GCM intent service. I use an rxBus that posts when the service is triggered. My activity subscribes to the bus and reacts when it sees the post.
I created sticky background service, that should be started on boot:
public class AutostartReceiver extends BroadcastReceiver
{
public AutostartReceiver()
{
}
#Override
public void onReceive(Context context, Intent intent)
{
context.startService(new Intent(context, MyService.class));
}
}
My service is intended to do some work in background, it's implemented by creating thread for this. Also there is Messenger class used for sending work status to my main activity:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "Service onStartCommand " + startId);
final int currentId = startId;
Messenger callback = null;
if(intent!=null)
{
callback = intent.getParcelableExtra("messenger");
}
final Messenger finalCallback = callback;
Runnable r = new Runnable()
{
public void run()
{
... do something, then stop
stopSelf();
}
};
if(t == null)
{
t = new Thread(r);
t.start();
}
return Service.START_STICKY;
}
Main activity receives messages sent from background thread running inside my service (some commands, that service is sending periodically:
Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case 0:
Toast.makeText(MainActivity.this,"Service runing", Toast.LENGTH_LONG).show();
break;
}
}
};
This works only if I start my service from activity, with activity's context. Obviously, if service is started on boot, or my app was closed (removed from last app list) and opened again, my activity is unable to get any messages from service any more.
If I invoke start service while service is already running, it will simply run OnStartCommand again, so either new thread will be created (I don't want it) or I need to destroy running thread and run thread again.
Is there any way to get my activity receiving messages from service, without actually touching already running thread inside it? I know about bound services, but it's not clear for me how to use them in my specific case.
As Alternate way You can use LocalBroadcastManager to send Data from Service to Activity.
Broadcast Your message from Service:
private void broadcastMessage(Context context){
Intent intent = new Intent("UI_UPDATE_BROADCAST");
intent.putExtra("MESSAGE", "MyMessage");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
Register Broadcast Receiver in your activity to receive messages:
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(mContext).registerReceiver(mMessageReceiver, new IntentFilter("UI_UPDATE_BROADCAST"));
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mMessageReceiver);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do Something With Received Data
String msg = intent.getStringExtra("MESSAGE");
}
};
I would use a broadcast receiver for Service-to-Activity communication.
Code:
public class MyActivity extends Activity {
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Toast here
}
#Override
protected void onCreate(Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, new IntentFilter("message-name"));
}
#Override
public void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
super.onDestroy();
}
}
Then in your service you would broadcast the message like this:
Intent intent = new Intent("message-name");
intent.putExtra("data", 1);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
I want to listen the power key event in the service.
How can in do that ?
Currently I am working with an app, where I need to listen the power button for some events, from a service which is running in a background, even when the app is killed or stopped.
Somehow I can manage to get it.
But when I kill/stop the app, the service is getting stopped.
How can i overcome this ?
Currently the code i am using this :
Service Class:
public class SampleService extends Service
{
SettingContentObserver mSettingsContentObserver;
AudioManager mAudioManager;
private ComponentName mRemoteControlResponder;
private Intent intent;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.v("StartServiceAtBoot", "StartAtBootService -- onStartCommand()");
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
Toast.makeText(getApplicationContext(), "On", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Off", Toast.LENGTH_SHORT).show();
}
}
public void onCreate()
{
mSettingsContentObserver = new SettingContentObserver(this,new Handler());
getApplicationContext().getContentResolver().registerContentObserver
(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mRemoteControlResponder = new ComponentName(getPackageName(),
StartAtBootServiceReceiver.class.getName());
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new StartAtBootServiceReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onDestroy()
{
getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
}
}
BroadcastReceiver Class:
public class StartAtBootServiceReceiver extends BroadcastReceiver
{
static boolean wasScreenOn;
private boolean screenOff;
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
wasScreenOn = false;
Toast.makeText(context, "Power Off", Toast.LENGTH_SHORT).show();
}
else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
wasScreenOn = true;
}
Intent i = new Intent(context, SampleService.class);
i.putExtra("screen_state", screenOff);
i.setAction("com.example.antitheft.SampleService");
context.startService(i);
//
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i1 = new Intent();
i1.setAction("com.example.sampleonkeylistener.MainActivity");
context.startService(i1);
}
}
}
given above is the sample code and i have created AndroidManifest.xml files also with user's permission but i cannot get the app continue service if it is killed or stopped.
Thanks in Advance.
#Override
public void onDestroy() {
super.onDestroy();
startService(new Intent(this, SampleService.class));
}
This is one way to ensure that service will never stop even user want to destroy it.
This is one Just ONE of ways to achieve what you are trying to achieve.
Secondly, you can try and run service in "foreground" by using startForeground().
Also, make sure that in you return "START_STICKY" (which you are doing in the sample code that you shared and I trust that you are also doing in App's code too :) ) in Services's onStartCommand().
This will ensure that If this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service.
And you may find some additional pointers/hints to make sure your service is not stopped at below link.
How can we prevent a Service from being killed by OS?
Just pick and choose the approach that best suits YOUR Need/implementation.
I have service which is basically timer. It receives object with location data, start time, user id etc, and every seconds it increments stop value. I'd like to have this service running non-stop until stopped in application. I've read that i need to start this service as sticky, so i did that. But I've noticed that after my main application is beeing killed by system or user, service restarts and lose all information (about current timers running etc - I have there array with list of objects).
Idea of that service was that:
user clicks button in app -> service is starting and counting time changing information in notification bar and sending broadcast to main application -> I wish to continue updating notification bar even if app is killed by user or system.
My class below:
public class TimerService extends Service{
private NotificationCompat.Builder builder;
private static JsonHistoryList activities;
private Intent intent;
private Handler handler;
private Runnable sendUpdateToUi = new Runnable() {
#Override
public void run() {
sendBroadcast();
handler.postDelayed(this, 1000);
}
};
private NotificationManager mNotificationManager;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(ACTION_ADD)){
JsonHistory item = (JsonHistory) intent.getSerializableExtra(HISTORY_ARG);
new NetworkAsyncTask().execute(ACTION_ADD_ID, item);
}else if(action.equals(ACTION_DELETE)){
int id = intent.getIntExtra(CATEGORY_ID_ARG, -1);
if(id > 0){
new NetworkAsyncTask().execute(ACTION_DELETE_ID, id);
}
}else if(action.equals(ACTION_CLEAR)){
activities.clear();
}
}
};
public TimerService() {
handler = new Handler();
}
private void sendBroadcast() {
Long time = new Date().getTime();
for(JsonHistory item: activities){
ContentValues values = new ContentValues();
values.put(History.C_STOP, time);
String[] selectionArgs = {String.valueOf(item.id)};
getContentResolver().update(History.URI, values, History.C_ID + "=?", selectionArgs);
item.stop = time;
}
intent.putExtra(ACTIVITY_LIST_ARG, activities);
Intent bIntent = new Intent(this, MainActivity.class);
bIntent.putExtra(CATEGORY_ARG, activities);
builder.setContentText(String.format(getString(R.string.notification_bar_message), activities.size()));
Notification barNotif = builder.build();
mNotificationManager.notify(SERVICE_ID, barNotif);
sendBroadcast(intent);
}
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_ADD);
filter.addAction(ACTION_DELETE);
filter.addAction(ACTION_CLEAR);
registerReceiver(receiver, filter);
intent = new Intent(ACTION);
handler.removeCallbacks(sendUpdateToUi);
handler.postDelayed(sendUpdateToUi, 1000);
activities = new JsonHistoryList();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if(intent != null && intent.hasExtra(TimerService.ACTIVITY_LIST_ARG)){
ArrayList<JsonHistory> temp = (ArrayList<JsonHistory>) intent.getSerializableExtra(TimerService.ACTIVITY_LIST_ARG);
if(temp != nu;; && temp.size() > 0)activities.addAll(temp);
}
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent bIntent = new Intent(this, MainActivity.class);
PendingIntent pbIntent = PendingIntent.getActivity(this, 0, bIntent, 0);
builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(getString(R.string.app_name))
.setContentText(String.format(getString(R.string.notification_bar_message), activities.size()))
.setAutoCancel(true)
.setOngoing(true)
.setContentIntent(pbIntent);
Notification barNotif = builder.build();
this.startForeground(SERVICE_ID, barNotif);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
handler.removeCallbacks(sendUpdateToUi);
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private class NetworkAsyncTask extends AsyncTask<Object, Void, String>{
Gson gson;
public NetworkAsyncTask() {
super();
gson = new Gson();
}
#Override
protected String doInBackground(Object... params) {
Integer actionId = (Integer) params[0];
String result = null;
switch (actionId){
case ACTION_ADD_ID:
break;
case ACTION_DELETE_ID:
break;
default:
result = null;
break;
}
return result;
}
}
}
Thanks for any replies
When you stop the service it is true it loses its information if the application is destroyed. That is because that instance of the service is tied to that particular instance of the application.
In my opinion, an easy fix would be to store the information you still need in some type of persistent storage (SQLite, Internal/External Memory, Shared Preferences)
Then, every time you start your service with a new application launch just be sure to reload the information you want from whichever persistent storage method you choose.
Also, assuming you don't want this service to continue if the application is killed by the user, be sure to send an intent to the service to stop it like this:
intent = new Intent(this, BackgroundLocationService.class);
stopService(intent);