I want to create an android app
that will send the device location after the app's installation
and every 15 minutes
What is the best way to do so?
1) I can create a timer inside the App's main Activity.
but then it will be stopped when the app is on the background. So I understand I have to create a service.
But then, how do I register it to work from device start up (after turning the device on and forever after)?
2) I saw this push notification tutorial, I think it doesn't fit my needs as the server sends the notification in broadcast, no?
I want different notifications to users based on their current location.
I want the user to actively send GPS location and then receive custom push to his location
(GEO based push notification)
Would you use something like the guy answered here?
If you want to do something on a time-based interval, I suggest looking into AlarmManager:
Alarms (based on the AlarmManager class) give you a way to perform time-based operations outside the lifetime of your application.
http://developer.android.com/training/scheduling/alarms.html
You can start the service by making a broadcast Receiver which listens to boot completed. Then start service in it. As far as getting location every 15 minutes is concerned you can use following code to get location every 15 minutes :-
locationManager.requestLocationUpdates(usedLocationService, updateTime, updateDistance, this);
replace updateTime with 90000 for 15 minutes. You should implement locationManager in your service.
If you are using google map android api, then there is a interface calls
locationOnChange(LatLng points), this will be called every X min or sec ( X is defined by you ), that bascially gets your current location at giving LatLng point. Then if I was you, I would use NotificationManager to push the notification with the updated point to my phone
Here is the code I would do for this.
//At OnCreate
mLocationClient = new LocationClient(this, this, this);
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationClient.requestLocationUpdates(mLocationRequest, this)
//Google Map interface
#Override
public void onLocationChanged(Location location)
//inside I would use the notificationManager to push the location
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
context).setSmallIcon(R.drawable.btn_star)
.setContentTitle("My notification~~~~")
.setContentText("Hello World!~~~~")
.setStyle(new NotificationCompat.BigTextStyle().bigText(s));
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(123, mBuilder.build());
Related
it kills background service, to solve your issue you should use foreground service.
my background sticky service is kill on oreo and heigher devices any solution for getting location on background service when Activity is on backound
It's because of Android Oreo behaviour changes for background execution. Suggested alternatives are
1) Foreground service.
Use this if you are ok displaying notification to the user when you are trying to retrieve the location using Location API. This would be reliable and is suggested in the documentation.
Sample app from the documentation :
LocationUpdatesForegroundService project on GitHub
An example of an app that allows the app to continue a user-initiated
action without requesting all-the-time access to background location.
References
https://developer.android.com/training/location/receive-location-updates
2) Work Manager
This approach would be less reliable as you will not be able to control when exactly this would be called but can be used if you don't want to show notification to the user at all.
You would not be able to run background services long running in Oreo as there are behavior changes, now Oreo to optimize system memory, battery etc, it kills background service, to solve your issue you should use foreground service.
Have a look at Background execution limits https://developer.android.com/about/versions/oreo/android-8.0-changes
A suggestion from me, if you can use FCM then go for it, because apps like WeChat, Facebook uses it, to deliver notifications and they don't face any problem.
Alternate solution which I have opted without FCM due to client requirement to run service that updates location in background. Here are steps below:-
You need to start your background service with showing notification in Oreo and above.
Them after that you need to keep in mind that after some time phone enters into Doze mode so you have to tackle that also
In Addition, Battery optimization must be disabled for the application too.
In Some custom ROM you need to manage the Auto-start permission to restart your service if the service is killed by the android.
And the most important part is, if the service is killed by the android system then send a Broadcast Message to the Broadcast receiver to restart your service one again
Hope you will do some more R&D work.
I have shared my experience and the process by which i have done the same to run the service in the background.
you must show notification for ForegroundService
public class ForegroundService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
//do heavy work on a background thread
//stopSelf();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
and add permission
<uses-permissionandroid:name=”android.permission.FOREGROUND_SERVICE” />
i want to make a notification when the app is closed.
Im new to Java and i dont now if a need a service or use AlarmManager.
My idea is to make a txt(in my server) with a number, if is 0 dont make the notifiacion, if is 1 make the notificacion and read all the content of other txt and use that text in the notificacion.
I need to check the txt with the number every 1 hour.
And i need this to happen even if the app is closed.
Thanks
What you want to do is called push messaging I recommend looking at Firebase https://firebase.google.com/docs/cloud-messaging/ or Amazon's implementation.
Services are exactly what you are looking for.
They run in background
Can be started again, even if the application is cleared from recent apps
Can be timed to suit your requirements
Very easy to implement
Here is the official documentation.
And this can be a good start tutorial.
You can use this code for sending notification. But do not forget this, onStop method is also valid for clicking on home and recents button. So, whenever you click on home or recents button, a notification will pop up. You can improve this code by listening home and recents button.
public void onStop() {
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.icon24)
.setContentTitle("App Closed")
.setContentText("You've closed the app")
.setTicker("You've closed the app")
.setAutoCancel(true)
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.icon96))
.setDefaults(Notification.DEFAULT_ALL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notificationBuilder.setPriority(Notification.PRIORITY_HIGH);
}
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
super.onStop();
}
I am trying to create a notification after every 2 mins but , only single notification is getting created(when app is started).
My code is :
notifyme.java :
public class notifyme extends Service {
#Override
public void onCreate() {
super.onCreate();
Intent intent=new Intent(this,MainActivity.class);
TaskStackBuilder stackBuilder=TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent=stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notify=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Hello")
.setContentText("Some random text")
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManager nMgr=(NotificationManager)this.getSystemService(this.NOTIFICATION_SERVICE);
Random r=new Random();
int nid=r.nextInt(50000)+1;
nMgr.notify(nid,notify.build());
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
In MainActivity.java :
Intent notificationIntent = new Intent(this, notifyme.class);
PendingIntent contentIntent = PendingIntent.getService(getApplicationContext(), 0, notificationIntent,0);
AlarmManager am = (AlarmManager) getSystemService(this.ALARM_SERVICE);
am.cancel(contentIntent);
am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),120*1000, contentIntent);
first you don't need a whole service to show a notification, if that's all it's doing, you could use a BroadcastReceiver and use PendingIntent.getBroadcast method. BroadcastReceiver needs less memory and doesn't have any life-cycle (which could complicate things).
The reason you're not seeing more than one notification is on the line nMgr.notify(119,notify.build());
This number 119 is the notification ID. So after X seconds that it's executing that code again, your new notification is directly replacing the old one and it all looks as if it hasn't changed.
If you want to put several notifications up (AKA. SPAM the user), you should always change that number. maybe using a Random
First of all, making new notifications in every two seconds is completely against guidelines.
As docs says :
When you need to issue a notification multiple times for the same type
of event, you should avoid making a completely new notification.
Instead, you should consider updating a previous notification, either
by changing some of its values or by adding to it, or both.
here the issue is that you are using the same ID to create the notification. (here 19).
When you publish a notification, if there is an active notification with the same id. notificatipon manager will update the existing one. So everytime the service is running, it just updates the notification with id "19".
If you are keen on issuing notifications on every 2 minutes (Which will affect the user-experience of your app very badly, let me warn you), try giving different ids to the notifications. You can save the issued ids in SharedPreferences or something.
I am working on an Android application in which I have to compare current time , with a time (saved) in a file, though everything is working fine. I have use services and in service i have use THREAD to run the service infinitely, and in addition to this i have also used PARTIAL_WAKE_LOCK to continue service even the device is sleep but the issue is that instead of acquiring PARTIAL_WAKE_LOCK my service runs for 1/2 hours and then again go to sleep. I don't want to acquire FULL_WAKE_LOCK. Is there any one who can guide me what i have to do in order to run this comparison, i.e. my service will run perfectly once the user set the time.
Thank you in advance.
You are doing it the wrong way. To create permanent service you must
declare it as foreground. No other way about it:
myService.startForeground(MY_NOTIFICATION_ID, my_notification);
If your interest with such a service is to periodically perform fast-ending
actions, and if the in between periods are long, you probably want to use
the alarm API and improve your app's battery consumption.
Edit:
To set a foreground service you must supply the system with a notification
object to be displayed at notification bar for as long as the service is in foreground
Why is that? Because foreground services cannot be killed, and Android needs to know
that the user is aware of that fact.
Setting as foreground:
static final int NOTIF_ID = 100;
// Create the FG service intent
Intent intent = new Intent(getApplicationContext(), MyActivity.class); // set notification activity
showTaskIntent.setAction(Intent.ACTION_MAIN);
showTaskIntent.addCategory(Intent.CATEGORY_LAUNCHER);
showTaskIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntent = PendingIntent.getActivity(
getApplicationContext(),
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notif = new Notification.Builder(getApplicationContext())
.setContentTitle(getString(R.string.app_name))
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pIntent)
.build();
startForeground(NOTIF_ID, notif);
And reverting to 'stardard' service mode:
stopForeground(true).
Both setting to foreground and reverting to background can be called by either the service itself (e.g. its onCreate() method) or by external code (e.g. the activity that initiated the service). No problems here.
I need some suggestions for approaches to take...
Here's some background info:
Right now I have an Android app and a separate java program running on my server.
The java program continuously go out and gets information from different sites and stores them in 14 different entries in an SQL database on the server.
The Android app then queries the databases to retrieve the info to be displayed.
My goal:
I need suggestions on how to have the app handle checking for updates from the database, and then letting the user know that there is new information.
My first thought is that maybe I need to start a separate thread that queries the database for a time modified. Then if it finds updates, it would pop up on the screen that there is new information.
I'm not too well educated with the way threads or services work, so I guess I'm looking for how to implement this, or whether there is a completely different way to go about update checking that would be better.
Thanks in advance, I appreciate any feedback, input, or suggestions.
Hi Ryan I have also implemented a similar thing in my android app and surprisingly I also had 14 tables in my PostgreSQL Server. First of all, you would want to poll the server periodically even when the app is not in the foreground. For that you need to run a background Service - here you will have to manually create a thread in the service, because Service by default runs on the UI thread OR use an IntentService - you don't have to create a separate thread. Whatever code you write in the intent service will be handled in a different thread automatically
Now you have to make this service execute periodically. For that use an AlarmManager and use the setRepeating()function. In the arguments you have to give a PendingIntent to your Service or IntentService. But don't use an alarm manager if you are going to poll the server for every less than 1 minute. Because the battery will be wasted a lot.
Here is some code that might give you an idea :
function setalarm()
{
Intent intent = new Intent(getBaseContext(), Intent_Service.class);
PendingIntent sender = PendingIntent.getBroadcast(getBaseContext(), 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Random randomGenerator = new Random();
long interval=60000; //1 minute in milliseconds
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(),interval,sender);
}
This is Intent_Service of type IntentService :
public class BackService extends IntentService
{
Context context=this;
//public Timer t=null;
public BackService()
{
super("myintentservice");
}
#Override
protected void onHandleIntent(Intent intent)
{
try
{
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
wl.acquire();
//..CPU will remain on during this section..
//make our network connections, poll the server and retrive updates
//Provide a notification if you want
wl.release();//Release the powerlock
}
}
}
But if you want instantaneous updates, then use Google Cloud Messaging Services. To know more about how it works see this
Hope this helps you.