I am building an app that is designed to run continuously. Furthermore, the user is locked into the app (via the pinning feature) when it is being used. When the app has not detected user interaction for a while, it unpins itself, calls the Android dream service, and displays a screensaver of sorts. When the user taps the device, it 'wakes up', goes to the main screen, and repins itself.
I need my app to auto-update. However, given the circumstances, I have had difficulty in doing so. It simply does not seem to update, or according to one of my colleagues, updated but closed the app.
Is there a way for the app to detect, download, and install an update while running, and then, if necessary, relaunch itself? What would be the best approach?
Thanks much.
Is there a way for the app to detect, download, and install an update while running
This is handled for you by google play store. An app is killed when it is going to be upgraded to a new version so the installation of the new version is smooth and data is not corrupted.
if necessary, relaunch itself?
If you want to keep running (or rather, restart the app) after an upgrade, yes you have to do some additional stuff.
A way that I use is this:
Put in manifest:
<receiver android:name=".receivers.AppUpgraded">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
public class AppUpgraded extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
// your app was just upgraded, restart stuff etc.
}
}
Note there is also a action.PACKAGE_REPLACED which will trigger for ANY app that is upgraded. You're likely only interested in the upgrade of your own app, so use action.MY_PACKAGE_REPLACED.
Related
I am new to Android development, but I have experience with Java.
My goal is to create an application that will try to connect to open Wifi AP when device gets unlocked (after screen on and pin/password is entered correctly).
This would ensure that application is run only before a user is going to use the phone so to save power while not in use. Also other ways of detecting when phone is actively in use while my application is not running in foreground.
My application is relatively linear:
1. Detect device unlocks (user is actively using the phone) state ore some other kind of trigger.
2. If wifi is on and the device isn't already connected to any AP, scan wifi.
3. If open AP's is in range select one with the strongest signal and try to connect.
Right now I am researching options how to detect device unlock state, but different API level limitations make it confusing. I am not planing to publish this application to play store so Google Play's target API level requirement doesn't bother me.I would like if my application could work on android 4.3 and up or android 5 and up if 4.3 is not possible.
These are the options I have come across right now.
1. Broadcast Receiver -> ACTION_USER_PRESENT
2. Job Scheduler for android 5 and up only (also fine by me).
3. Background service. Newer android versions would restrict these.
I am open to any suggestion and information, including problems that might come up in other steps.
Thanks.
Sorry!
I already had project created and I was testing multiple code snippets on AVD, but nothing seemed to work. Then I tried to run my application on my phone and turns out everything works as expected.
Class that will handle broadcast.
public class ConBroRec extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
//when device is unlocked
}
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<application ...>
...
<receiver android:name=".ConBroRec"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
...
</application>
...
</manifest>
targetSdkVersion<=25
The device we’re speaking about is an Android 8 head unit with an external USB keyboard attached.
Well, I need to assign some tasks to this keyboard’s function keys, e.g. launching certain applications. Say, F4 can launch the media player, F5 the navigation app and so on. Either the Automate or the AutoInput Tasker plugin would be nice for this purpose, but all of this kind of applications use accessibility service for interacting with physical HID devices.
The big problem here is that this particular Android device regularly kills the accessibility services on (warm) reboot. Tried absolutely everything, from disabling power save mode to mark the Automate etc. as device admin app, nothing helped. So I have resigned and now I’m thinking for an alternative way to re-enable the appropriate accessibility service after the system disabled it after reboot for an unknown reason.
If the device was rooted I suppose there would be an easy way to restart an accessibility service by a shell command or whatever (just guessing, I’m pretty beginner in Android). But obviously I want to avoid rooting if possible. The ideal scenario would be to (auto)start a shell command / application / foreground service / whatever on each reboot – which would have enough administrative privileges to re-enable the accessibility service the system just have disabled during the reboot. Of course, all this stuffs without rooting the device. But I’m not really sure this can be done on Android (on Windows it would be enough a service running in System account, but Android is a different story).
A fair solution might be to
root the device,
install the shell command (application, foreground service, whatever) meant to restart the accessibility service after each reboot and
unroot the device (using SuperSU by example) in order to protect the user and not to void the warranty.
Would anybody tell me whether the above solution can give the desired result, and – if so – may I have some guidelines how to do this?
to achieve your purpose you should work with BroadcastReceiver and jobIntentService
first create a boot receiver
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
MyService.enqueueWork(context, new Intent());
}
}
}
add it to the manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name=".MyService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
Now you have to define your jobIntent
public class MyService extends JobIntentService {
public static final int JOB_ID = 0x01;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, MyService.class, JOB_ID, work);
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
// your code
}
}
And that’s it. This will directly start the service (when running on pre-O platforms) or enqueue work for it as a job (when running on O and later). No matter what the platform is, everything you pass in enqueueWork will ultimately appears in onHandleWork.
here is some useful links : link - link
Many apps provide recommendations to install other applications made by the developer or developer's partners. The recommendations are just links to the Play Store where the recommended app may be installed from.
I don't want to provide a recommendation for app X if:
App X is already installed
App X is in the process of being installed (e.g. downloading on Google Play)
Detecting if X is installed is easy, but I can't seem to find any API to read downloading/installing state from Google Play. Is there any way to detect if the user is in the process of installing app X?
Is there any way to detect if the user is in the process of installing
app X?
The closest you'll get to this is by using a NotificationListenerService.
From the docs:
A service that receives calls from the system when new notifications
are posted or removed.
But considering this Service was recently added in API level 18 and your use case, you might consider using a BroadcastReceiver and listening for when android.intent.action.PACKAGE_ADDED and android.intent.action.PACKAGE_REMOVED are called. This way once an app is installed or removed, you can do what you want with the package name, like provide a link to the Play Store.
Here's an example:
BroadcastReceiver
public class PackageChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getData() == null) {
return;
}
final String packageName = intent.getData().getSchemeSpecificPart();
// Do something with the package name
}
}
In your AndroidManifest
<receiver android:name="your_path_to.PackageChangeReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
I am aware of one way to do it. However, it will require you to initiate the download from a URL.
The simple idea behind is to use
getContentLength()
to see the content length of the app in bytes.
Then, you can simply use
YouInputStream.read(TheData)
to see the progress of the download.
There is actually a much more detailed answer on how to do this over at Download a file with Android, and showing the progress in a ProgressDialog
On that note, maybe you can get access to the socket on which the app is being downloaded and then follow the same steps from above. I don't have any experience with this tho.
In my Application I am not having any UI part, so I need to start a Service as soon as the Applicaton gets installed on the Device. I saw many links from which the answer was that its not possible but I guess it is surely possible. Just have a look at PlanB Application on the Android Market that does fulfil my requirement. Below is my Manifest file how I tried, but the Service was not called at all. So, let me know what is the best possible way to start a Service when the Application gets Installed.
UPDATE
I also tried using android.intent.action.PACKAGE_ADDED it works fine for detecting the Package for the other Applications but not for itself.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.auto.start"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:icon="#drawable/ic_launcher" >
<service android:name=".MyService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
<receiver android:name=".BootUpReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
</application>
</manifest>
Fortunately, Plan B does not work on Android 3.1+, as tested on a XOOM and a Galaxy Nexus.
What Plan B does is exploit a security hole that could be used by drive-by malware, which is specifically why Android prevents it from happening anymore.
UPDATE
To clarify: As inazaruk posted and I put into comments on other answers, all applications, upon installation, are placed in a "stopped" state. This is the same state that the application winds up in after the user force-stops the app from the Settings application. While in this "stopped" state, the application will not run for any reason, except by a manual launch of an activity. Notably, no BroadcastReceviers will be invoked, regardless of the event for which they have registered, until the user runs the app manually.
This block covers the Plan B scenario of remote-install-and-run, which they were taking advantage of previously. After all, with that, anyone with a hacked Google account would be at risk of having their device infected, hands-free as it were.
So, when the OP says:
I need to start a Service as soon as the Applicaton gets installed on the Device
the OP will be unsuccessful and will need to redesign the application to avoid this purported "need".
Applications installed on the /system partition are not subject to being placed into the "stopped" state after installation. If you have root, you can do,
$ adb root
$ adb remount
$ adb push your.apk /system/app
And it can immediately receive broadcast intents. This certainly doesn't provide a general purpose solution, but i wanted to mention it for completeness.
EDIT: Keep in mind that different versions of Android locate system APKs in different places. For example, Android 8 puts them under /system/app//.apk. Shell into your device and poke around and follow the same scheme used for other system APKs.
I agree with CommonsWare's answer to question: How to start android service on installation. In other words, you can't automatically start your service after you've just been installed.
One more thing about newer Android platforms: if you don't have UI at all, you'll have trouble starting your service even when using BOOT_COMPLETE intent on Android 3.1+.
That's because all installed applications are in stopped state. In this state applications will not receive ANY broadcast notifications.
In order to activate your application some other application (or user) needs to start your service or activity, or content provider. The usual workflow is when user clicks on your application's icon.
I've written a detailed explanations about this in my blog post.
Plan B does this launch by listening to the events which happen in the system. It uses a receiver which literally listenes to hundreds of events hoping that some of them will eventually fire up. So this is how you can do it. Otherwise, there are no built-in means to launch the application as soon as it gets installed.
I'm not sure what your constraints/purpose is, but if you can install another application that has an activity you can have it send an intent with the flag FLAG_INCLUDE_STOPPED_PACKAGES.
This will use your application for the intent resolution, even though it's in a stopped state. If the action of the intent matches one of your filters, it will also bring the package out of the stopped state.
I don't think so You can start service immediately after installed your application on device,
The application must first be invoked by the user through some sort of Activity.The only things you have to register some Broadcast Receiver with appropriate intents in manifest which invoke you service when something is happening on device but this remaing to Android 3.1 version.
EDIT:
After Android 3.1+ onwards you can not use any Broadcast for starting your application, because all application remains in inactive state after completion of device boot and to launch the application the user have to invoke it.(By touching the app icon).
As stated by CommonsWare in the answer to this question (which I suppose you have all ready seen, but chose to ignore) starting a Service on install is not possible - it is simply not a thing that is implemented into the platform.
Starting it automaticly at the next boot is however possible.
As stated in the Technical Details for PlanB:
Plan B will attempt to launch as soon as it downloads, but in some cases you will need to send an SMS to get it started.
My guess is that on a rooted phone you might be able to start the Service on install - but there's no guarantee that the phone is rooted, which is why PlanB will require recieving a text in some cases because that can be registered by the IntentFilter of the app and then used to start the Service.
there is an app on google play Android Lost which invoke the registration service for google push messages via an incoming sms without launching the app even once for version 3.0+.
Perhaps the best way to accomplish this (and now I'm speaking to the specific intent of the OP, a program that gets installed in order to retrieve a stolen phone, not the general question) is social engineering, not software engineering.
So, an icon with text like "Password List" or "My Bank Accounts" which suddenly appeared on the home screen would undoubtedly be clicked on. Look at the success of all sorts of other phishing, and here you would be targeting a thief, who's already motivated to continue nefarious activity. Let the thief start it for you. :)
HEY I think using a BroadcastRecivier to automatically start the app on restart of device hence it will automatically start on device start.Hope this will help
Does anyone know if a specific method is available to be overridden when my application is uninstalled? It would be nice to remove these users from the server side database when this occurs.
Unfortunately there is currently no way for an Android package to execute code when it is removed. However, you can register a BroadcastReceiver for ACTION_PACKAGE_REMOVED in a different package that will be called when packages are removed from the phone.
Also see this question.
I know I'm late to the party, but I'm guessing that since for you uninstalling the app is sufficient to blow away the user at the server (as opposed to the user explicitly picking a "delete my account" option), I would create a job on the server/service-side that scans for inactive users every N units of time (eg. 30 days) and deletes them. Why? An app that never connects to your server is as good as an app that is uninstalled.
However, you can then build logic in your app to handle the case when those users that never uninstalled the app, but don't log in for over N units of time, eventually come back. Then, you could:
make the app send a special "I'm already installed" cookie to the server, which then instructs the app to send it enough app-side cached info to reconstruct the user data at the server while saying "Please wait, syncing with server...". This should work as long as the user data is not huge (for eg. some sort of image library), and if it is, your best bet then is to indicate in BOLD letters that inactive accounts will be deleted.
Or, of course, you could also just reset the app to its original state and hope the user does not hate you.
You could go the route to install a service as part of your app that wakes up once a day and when WiFi is available and the device is on A/C power, sends a "heartbeat" to your service saying "I'm installed". If the heartbeat stops for more than a few days, you can assume the user uninstalled the app and delete the user data. But note that this is not foolproof, since the user may simply have turned the device off for that many days. In which case, you now have to handle the situation when a heartbeat comes in for a user that is no longer active in the system, at which point you will need to build in reconstruction logic as before (which buys you nothing for having gone through this pain of building the heartbeat, thanks a lot), or, you simply reset the app to its fresh state and hope the user doesn't hate you (which again buys you nothing for having gone through this pain of building the heartbeat, thanks a lot).
Those pesky users! ;-)
Yes, there is a way where you can Use Android listener application to install and uninstall App.
App install and uninstall will send a broadcast when the application installation is complete, the system will listen android.intent.action.PACKAGE_ADDED broadcast. The name of the package that was installed by intent.getDataString(). When the uninstall program system listens android.intent.action.PACKAGE_REMOVED the radio. The same intent.getDataString() to get the the uninstall package name. The application can not monitor the installation and uninstallation, but cover the installation can listen to their own android.intent.action.PACKAGE_REMOVED broadcast.
Example
AndroidManifest.xml configuration file:
<receiver android:name="com.sarbjot.MyApp.BootReceiver" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
And the receiver call:
package com.sarbjot.MyApp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// install call
if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
//code here on install
Log.i("Installed:", intent.getDataString());
}
// uninstall call
if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
//code here on uninstall
Log.i("Uninstalled:", intent.getDataString());
}
}
}
I hope it will help you all.
Yes, You can handle it by identifying click on Uninstall Button from Settings -> Manage Apps -> Selects a particular application.
try this answer.
Hopefully this will works.