Locations updates stay active when Android app is not longer active - java

I have the following problem: I send in regular interval GPS data from the mobile to a server. In fact I want this background service only running as long the user is willing to submit data. There should be some sort of confirmation dialog that from now on data are submitted and then these submissions should be active - event if the App is shutdown meanwhile - until the user again confirms that data should be no longer sended:
Here is my current entry in the AndroidManifest.xml:
....
<receiver
android:name="ch.bbcag.jumpin.app.receiver.gps.ConnectivityReceiver"
android:process=":gps_process" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver
android:name="ch.bbcag.jumpin.app.service.LocationUpdaterService"
android:process=":gps_process" />
<service
android:name="ch.bbcag.jumpin.app.service.LocationUpdaterService"
android:process=":gps_process" />
....
GcmIntentService.java:
public class ConnectivityReceiver extends BroadcastReceiver {
private static final int EXEC_INTERVAL = AppConstants.GPS_REPEAT_SECONDS * 1000;
private final static String TAG = "ch.bbcag.jumpin.app.receiver.gps.ConnectivityReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received event");
final AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
final PendingIntent wakeupIntent = PendingIntent.getService(context, 0,
new Intent(context, LocationUpdaterService.class),
PendingIntent.FLAG_UPDATE_CURRENT);
final boolean hasNetwork = !intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (hasNetwork) {
context.startService(new Intent(context,LocationUpdaterService.class));
Calendar now = Calendar.getInstance();
now.add(Calendar.SECOND, AppConstants.GPS_REPEAT_SECONDS);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), EXEC_INTERVAL, wakeupIntent);
} else {
alarmManager.cancel(wakeupIntent);
}
}
}
The problem with this approach is that event the user is not using the App events are sent to the server. A simple solution would be in the class LocationUpdaterService to check in preferences if app should really send events. But the fact stays that LocationsUpdaterService is called regularly even if I don't use it (and Android wastes time to call this service).
How I can figure this out? Articles? Code examples are welcome!

How I can figure this out?
Only schedule your alarms when you need them. If you no longer need them, cancel the alarms.
Also, if you are going to use RTC_WAKEUP, either use WakefulBroadcastReceiver or my WakefulIntentService, otherwise your alarms will not be reliable.
Also also, your manifest is malformed. Either ch.bbcag.jumpin.app.service.LocationUpdaterService is a <receiver> or it is a <service>, but it cannot be both.
And also also also, dump the android:process=":gps_process" unless you have a clear understanding of why you are using it and its costs to you and the users.

I just have to read the documentation from Google to get aware how things are really working:
1) I don't want to start the Alarm when the device boots:
Solution:
(AndroidManifest.xml)
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".SampleBootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
Notice that in the manifest, the boot receiver is set to
android:enabled="false"
This means that the receiver will not be called unless the application explicitly enables it. This prevents the boot receiver from being called unnecessarily. Once you have started the your App you can:
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
From this point on the GPS locations are send in regular intervals to the server. Once you have done this, the next time the receiver will start on boot up. This is what i want to prevent.
2) Prevent automatically starting BootReceiver from boot:
For this purpose I'm looking for a possibility to get the shutdown event of the Android system:
<uses-permission android:name="android.permission.DEVICE_POWER" />
<receiver android:name=".ShutdownReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
public class ShutdownReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);
}
}
This has the effect that next time the mobile boots it will not start automatically the SampleBootReceiver until you explicitly specify this with the code:
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
3) Conclusions:
a) Once your App is started the Receiver is activated: GPS coordinates go in regular intervals to the server
b) In your App you can make a setting to terminated the receiver or to enable it.
c) Finally if the handy shut down it's time to remove the receiver.
d) The next time you can restart with a)

Related

Android Start service at specific time using AlarmManager and also device boot complete

I wont start service at specific time everyday and also start when the device boot complete.
For example.. at 13.00 Pm everyday the service started and show a Toast ("Service started").
not only that, but the service has to start also at boot complete but if you are not the 13.00 pm should not show the toast but must started
For boot complete define receiver for ACTION_BOOT_COMPLETED
Start service at boot complete
For Specific time, use AlarmManager
Start Service At Specific Time
public class onBootComplete extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
//Do your task here
}
}
}
And in Manifest declare this..
<receiver
android:name=".onBootComplete"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="500" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Add this permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
For timed actions use AlarmManager
This class provides access to the system alarm services. These allow
you to schedule your application to be run at some point in the
future. When an alarm goes off, the Intent that had been registered
for it is broadcast by the system, automatically starting the target
application if it is not already running.
check this link ,it will help you How to repeat notification daily on specific time in android through background service

Run Android app in background without user interaction

I have an android app which keeps updating logs every 5 minutes.
I used Alarm Manager to achieve this.
But the app kept opening and closing automatically.
Is there any way to do this in background??
you can use android Services for this task.
http://developer.android.com/guide/components/services.html
First of all, you have to user `Service: http://developer.android.com/guide/components/services.html
Next, you can start your program in background on BOOT event:
public class BootReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, LogService.class);
context.startService(myIntent);
}
Declare theese in your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Declaring broadcast receiver for BOOT_COMPLETED event -->
<receiver android:name=".BootReciever" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

how to start activity when android turned on?

I have the next code:
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startActivityIntent = new Intent("android.intent.action.MAIN");
startActivityIntent.setClass(context, MainActivity.class);
startActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityIntent.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
context.startActivity(startActivityIntent);
}}
And the manifest:
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="false" android:label="BootCompleteReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME"/>
</intent-filter>
</receiver>
It works perfectly when I turn on the device the activity starts, but I think it take about 30 seconds, I think is too much time, I want to do something like the Famigo's app, when the device is turned on inmediately start.
There is no way for you to speed up this process. It takes 30 seconds on your device, because the program has to wait until your device is completely booted. Boot_Completed is the first notification that the system sends out after boot.
Google has done this intentionally to prevent apps from starting before the system is finished booting.
the reciver calls BootCompleteReceiver, the reciver will start after the boot will complete.
it takes about 30 seconds.
you cant start the app before the OS!

Stop SMS Receiver

I am using SMS Receiver Service which starts from Android Manifest File, using the following code. The problem is that it will remain working even after the application exits. How do I stop this service from receiving SMS?
Start Service CODE:
<receiver android:name=".dataAccess.SMSReceiver" android:enabled="true">
<intent-filter >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
If you want to keep using a broadcast receiver defined in your manifest, you can still enable / disable it using the package manager.
Check here
ComponentName receiver = new ComponentName(context, SMSReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP)
Quick correction before I continue: that's not actually an Android Service, it's a BroadcastReceiver.
The easiest way is to listen for Pause/Resume of your application, and register/unregister the SMS receiver there. Here's a sample snippet from the Wi-Fi Direct tutorial.
#Override
public void onResume() {
super.onResume();
receiver = new SMSReceiver(...);
registerReceiver(receiver, intentFilter);
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}

Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED

I worked through the description and samples for USB host at developer.android.com to detect attached and detached USB-devices.
If I use an intent-filter in the manifest file to start my application when a device is attached, it works perfectly fine: Plug in, device is detected, android asks for permission to start the application, device information is displayed in a table.
The application I'm developing shouldn't be started/finished only if a device is attached/detached (e.g. data management purposes). Also I do not want the open-dialog to pop up if the app is already running. So I decided not to start the activity directly if a device is attached, but to register a BroadcastReceiver, which is (later) supposed to notify the activity if a device is at-/detached. This receiver recognizes the detach-action just fine, but not the attach-action.
Am I missing a permission or data attribute or something like that? The tutorial and samples don't say anything about additional necessary attributes.
Here is the manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="de.visira.smartfdr"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12" />
<uses-feature android:name="android.hardware.usb.host" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".usb.Detector">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
android:resource="#xml/device_filter" />
</receiver>
</application>
And the receiver:
public class FDRDetector extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(context, "Action: " + action, 3).show();
// pops up only if action == DETACHED
}
I don't understand why the same intent-filter works, if I use them on an activity, but not if they are applied to a receiver? Even if I set up the receiver and filter in code, attaches are not recognized.
My work environment:
IDE: Eclipse 3.7 with Android Plugin
Device: Acer Iconia Tab A500
Android: 3.1
Thanks in advance
Aha! I figured it out. I was having the exact same problem.
The gist of it is - if you have your application launch automatically when a device is plugged in (using the manifest file), then it appears the Android system gets the ACTION_USB_DEVICE_ATTACHED intent, and then since it knows your application wants to run in that situation, it actually sends your application the android.intent.action.MAIN intent. It never sends the ACTION_USB_DEVICE_ATTACHED action to your application because it thinks it already knows what your application wants to do in that situation.
I've just now identified the problem, and I think I have a solution, but I can tell you what I've found:
Even if your app is running and in the foreground, when you plug in the USB device and the Android system gets the ACTION_USB_DEVICE_ATTACHED intent, it will call onResume() in your activity.
Unfortunately, you cannot just do this:
#Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Log.d(TAG, "intent: " + intent);
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
//do something
}
}
Because the intent will come back as android.intent.action.MAIN, NOT ACTION_USB_DEVICE_ATTACHED.
An annoyingly, you also get android.intent.action.MAIN if you just leave the app, but don't unplug USB. I imagine putting the device to sleep and waking it back up will do the same thing.
So from what I have found, you can't get the intent directly, but it does appear that you can rely on onResume() being called when a USB device is plugged in, so the solution is to just check to see if USB is connected every time you get an onResume. You can also set a flag when USB is disconnected, because of course the USB disconnect intent fires just fine.
So in total, your broadcast receiver might look like this:
// BroadcastReceiver when remove the device USB plug from a USB port
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
usbConnected=false;
}
}
};
You'd have this inside of onCreate:
// listen for new devices
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mUsbReceiver, filter);
This goes inside of the activity tag in your manifest:
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
You'll have a device_filter.xml file in your /res/xml/ folder that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1027" product-id="24577" />
<usb-device vendor-id="1118" product-id="688" />
</resources>
(of course with whatever vendor IDs and product IDs you need)
And then your onCreate looks something like this:
#Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Log.d(TAG, "intent: " + intent);
String action = intent.getAction();
if (usbConnected==false ) {
//check to see if USB is now connected
}
}
I don't have specific code for checking to see if USB is connected as I actually haven't delved into that yet. I'm using a library that will just connect if it can, so for my application I can just start that loop and I'm good.
Its also probably important to set the launchmode of your activity in the manifest to "singleTask" to prevent it from running again when its already running, or else plugging in a USB device will just launch a second instance of your application!
So my whole activity tag in my manifest looks like this:
<activity
android:label="#string/app_name"
android:name="com.awitness.common.TorqueTablet"
android:theme="#android:style/Theme.Holo.NoActionBar.Fullscreen"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTask"
>
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
</activity>
Anyway, I hope this helps someone! I was surprised that I was unable to find a solution for this already!
Just to follow on from #Gusdor's insightful comment (+1): I implemented a check in onNewIntent() that, as #Gusdor points out, is called when your activity launchMode is set as singleTask or singleTop. Then, rather than checking for boolean flags as the accepted answer suggests, simply pass on the intent to your USB broadcast receiver using a LocalBroadcastManager. For example,
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction())) {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Then, wherever you're registering your existing (system) USB broadcast receiver, just register the same receiver with a local broadcast manager instance, i.e.,
#Override
protected void onResume() {
super.onResume();
myContext.registerReceiver(myUsbBroadcastReceiver, myIntent); // system receiver
LocalBroadcastManager.getInstance(myContext).registerReceiver(myUsbBroadcastReceiver, intent); // local receiver
}
#Override
protected void onPause() {
super.onResume();
myContext.unregisterReceiver(myUsbBroadcastReceiver); // system receiver
LocalBroadcastManager.getInstance(myContext).unregisterReceiver(myUsbBroadcastReceiver); // local receiver
}
You could send another system broadcast rather than a local broadcast, but I don't think you'll be able to use the action UsbManager.ACTION_USB_ACCESSORY_ATTACHED (system would see that as potential security risk), so you'd have to define your own action. No big deal, but why bother, especially as there's no IPC overhead with local broadcasts.
Creating the broadcast receiver within the application, and not the manifest, allows your application to only handle detached events while it is running. This way, detached events are only sent to the application that is currently running and not broadcast to all applications.

Categories

Resources