android not receiving Intent ACTION_PACKAGE_REMOVED in the removed package - android

When my android app is removed, I would like to also remove files the app has created on the SD card, as these can consume many megabytes and are only of use to my app.
It seems that receiving the PACKAGE REMOVED intent would be the place to do this.
However, my broadcast receiver is never called--it seems to have been deleted before the PACKAGE REMOVED intent is sent
The code is:
public class UninstallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action= intent.getAction();
Log.i("U", "ACTION " + action);
etc.
}
}
and, in the manifest:
<application android:debuggable="true"
android:icon="#drawable/icon"
android:label="#string/app_name">
<receiver android:name ="com.boom.UninstallReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package" />
</intent-filter>
</receiver>

The documentation says:
The package that is being removed does not receive this Intent.
Android 2.2 added getExternalFilesDir(), which will point to a place on the external storage that Android will automatically clean up when your application is uninstalled. However, that is only for Android 2.2, and there are indications that it does not work particularly well at the moment. However, it is something to keep in mind for 2011.
Beyond that, all you can really do is offer a menu choice somewhere for the user to do the cleanup, and hope users use it before uninstalling you.

Have you tried this?
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
registerReceiver(new UnInstalledReceiver(), filter);
Also, putting the files of your app in the folder android/data/com.boom/ is a nice easy way to make sure extra files get cleaned up when users uninstall.

You must add the permission in the manifast.
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />

Related

Android App to start automatically on Boot Up

I am trying to get my Android app to start automatically on boot up.
I have followed various examples and copied the code, but still, when I power up, the app does NOT start.
I am using a Galaxy Tab A7 Lite, running Android 11.
Any help gladly received.
Thank you.
Here is my code...
I have defined the receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class StartOnBootupReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent activityIntent = new Intent(context, MainActivity.class);
context.startActivity(activityIntent);
}
}
}
And in the AndroidManifest.xml file:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and
<receiver android:name=".StartOnBootupReceiver"
android:exported="false"
>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action..QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
Your code looks good and your receiver is most likely executing. However, it is crashing because of the call to startActivity(). Since Android 10, startActivity() can only be called if the application is already in the Foreground or if it meets one of the listed exceptions listed in the Android guide Restrictions on starting activities from the background.
As an aside, the value of the android:exported has no effect. The OS can still call receivers who have android:exported="false" and, in the case of exported="true", other application cannot send a broadcast with BOOT_COMPLETED or QUICKBOOT_COMPLETED because they are protected intent actions.
All your code is correct. However, if you look up android:exported="false" meaning you will find that:
The "exported" attribute describes whether or not someone else can be allowed to use it. So if you have "exported=false" on an Activity, no other app, or even the Android system itself, can launch it. Only you can do that, from inside your own application.
In your <receiver> statment, the android:exported="false" needs to be true.
That info borrowed from here and here.

Android Receivers not doing as expected

Well honestly, they aren't doing anything at all. Let me start by saying that I know that Android reworked receivers in 3.1, specifically boot control. I know that they made it so that ACTION_BOOT_COMPLETED cannot be used unless the application has been previously launched by the user. However, people have been successful in using them in current application, yet I am never hitting my receivers for my BOOT_COMPLETED or my SHUTDOWN.
Quick Edit - Please look at the bottom of this post for corrected Shutdown Receiver, I have gotten it to work and am now just stuck in my efforts to get BOOT_COMPLETED to work.
My manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.smashingboxes.speedblock"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="12"
android:targetSdkVersion="18" />
<!-- PERMISSIONS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<!-- RECEIVERS -->
<receiver android:name=".BootReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".ShutdownReceiver" >
<intent-filter>
<action android:name="android.intent.action.SHUTDOWN" />
</intent-filter>
</receiver>
Now my implemented receiver classes are fairly straight forward:
BOOT_COMPLETED Receiver (the one that isn't working)
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context c, Intent i) {
Intent starterIntent = new Intent(c, LaunchActivity.class);
// Start the activity (by utilizing the passed context)
starterIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.getApplicationContext().startService(starterIntent);
}
}
I have tried different things based on what I have seen as far as solutions, such as altering my launching activity to include
/* May need this, as of 3.1 we can't call BOOT_COMPLETED until the app has been run successfully */
Intent intent = new Intent("com.smashingboxes.speedblock.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
or including this in my boot receiver intent-filter in my manifest
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
Nothing seems to work. When Logs are inserted into my receiver methods they are never hit. Apparently people are still using these two receivers fairly regularly, which is why I am having trouble understanding why neither of them work. Have I missed something with my registration or something?
--EDIT--
I have solved the problem with my shutdown receiver. First, I foolishly forgot the ACTION_ portion of the tag. Secondly, HTC has separate shutdown methods, in my case I needed to add an intent-filter to my Receiver request:
<receiver android:name=".ShutdownReceiver" >
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
Now my Shutdown Receiver works, still no luck on the Boot Completed Receiver though.
I found the answer and I think that it is actually important to note, as it seems like an issue others will run into at some point. My issue was that I was launching a "Launcher Activity" called just that, LauncherActivity. Basically, it acted as my gateway to start up services, receivers, and such when the application was launched. It is a very simple Activity class:
public class LaunchActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
/* May need this, as of 3.1 we can't call BOOT_COMPLETED until the app has been run successfully */
Intent intent = new Intent("com.smashingboxes.speedapp.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
#Override
protected void onStart(){
super.onStart();
Intent serviceIntent = new Intent(this, MainService.class);
startService(serviceIntent);
// NOTE: It is VERY, VERY important that we DO NOT finish this activity.
// If we do, our BootReceiver will no longer receive its broadcast and
// we won't auto-start on boot
//finish();
}
}
Note that I was calling finish() on the LaunchActivity. The problem with this is that it seemed to tell Android that the application was in the stopped state, meaning that it won't allow the reception of the BOOT_COMPLETED broadcast, even though I had a number of services running in the background. The LauncherActivity MUST stay active throughout the entire life-cycle or the BOOT_COMPLETED receiver becomes useless. Something that I haven't really seen mentioned before, but again something I think is worth noting.

How to start the application after boot complete in android version 3.1 and above?

I got to know boot complete intent is not supported by android version 3.1 and above from here. But in my application. I want to start services automatically in my application after device is rebooted. I do not want user to start my application manually. How can I do it ? Thanks for help in advance.
What makes you think the ACTION_BOOT_COMPLETED broadcast is no longer sent? I make frequent use of it, and so do others. Just be sure you have RECEIVE_BOOT_COMPLETED permission in your manifest.
try the following steps to start the application after boot:
create a class which extends BroadcastReceiver:
public class AutostartService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("in broad....");
if ((intent.getAction() != null) && (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")))
{
System.out.println("in broadcast receiver.....");
Intent i = new Intent(context, Splash.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
and also add this in android manifest file:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".AutostartService" android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Well this is pretty old now and probably most people learned it but still might be useful.
From 3.1+ and on, in order to receive the BOOT_COMPLETED, your app must be started at least once by the user.
NOTE: This rule doesn't apply to /system apps

PACKAGE_ADDED BroadcastReceiver doesn't work

I have a broadcast receiver registered in Manifest:
<application ...>
<receiver android:name="com.some.pkg.NewAppReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
</intent-filter>
</receiver>
</appcication>
And the receiver:
public class NewAppReceiver extends BroadcastReceiver {
private static final String TAG = "NewAppReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Intent: " + intent.getAction());
}
}
And nothing is received when I install APK manually or from the Android Market. Why?
Did you run the app that contains this broadcastReceiver before installing the other apps?
Starting at some API version, broadcastReceivers will not work till you execute the app. Put an activity and execute it.
Also , don't forget to add the following into the broadcastReceiver:
<data android:scheme="package" />
EDIT: On Android 8 and above, if your app targets API 27 or more, it will work partially, so you have to register to those events in code and not in manifest. Here's a list of intents that are still safe to use in manifest: https://developer.android.com/guide/components/broadcast-exceptions.html .
The rest should be used in code. More info here
Since android.intent.action.PACKAGE_ADDED is a System Intent (note that your own app will not receive it at its installation), your BroadcastReceiver will receive messages from sources outside your app. Thus, check you did NOT put: android:exported="false"
You also may need to add:
<data android:scheme="package" />
So, your BroadcastReceiver in your AndroidManifest.xml should look like this:
<application ...>
<receiver android:name=".NewAppReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
</appcication>
If it still doesn't work, you may try to put an higher priority, such as: android:priority="1000"
Take a look at: http://developer.android.com/guide/topics/manifest/receiver-element.html
Registering receiver from manifest would not work from API 26(android 8). Because it had performance impact on older versions.
But we can register receiver from java code and receive updates of removed and added applications.
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
intentFilter.addDataScheme("package")
registerReceiver(YourBroadcastReceiver(), intentFilter)
Are you trying to receive the intent in the application you are installing? The documentation for ACTION_PACKAGE_ADDED says:
Note that the newly installed package does not receive this broadcast.
Another possibility is that this intent might not be delivered to components registered via the manifest but only manually (as described in an answer by Mark Murphy to Stack Overflow question Can't receive broadcasts for PACKAGE intents).
If you try to receive some other package it must be worked.
(As #Savvas noted) If you try to receive your own package's addition you can't receive it. Even if your broadcast receiver has action.PACKAGE_ADDED, receiver's onReceive method isn't triggered.
In this case your best bet is saving this data. By using sharedPreferences, add a key something like "appIsWorkedBefore", and on your launcher Activity's onCreate method set this variable as "true". And you can make your works with respect to this Boolean.
This intent action is no longer available for applications.
This is a protected intent that can only be sent by the system.
https://developer.android.com/reference/android/content/Intent#ACTION_PACKAGE_ADDED

Detect USB in Broadcastreceiver - what am I missing?

My code misses something, need your eyes to locate.
I created a USBOnReciever broadcastreceiver.
public class USBOnReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Phone was connected to power" ,Toast.LENGTH_LONG).show();
Log.d("tag", "Phone was connected to power");
}
}
My manifest is:
<application>
<receiver android:name=".USBOnReceiver" android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.UMS_CONNECTED" />
</intent-filter>
</receiver>
</application>
and here is when I stuck.
nothing appears to happen when connecting the USB ( I also tried with power_connected).
I understand I can register the BR either through the manifest or programmaticaly. But not sure how to implement.
In my activity I added
USBOnReceiver myReceiver = new USBOnReceiver();
But it looks so unconnected and useless :-/
Will appreciate your eyes here.
Your code is seems complete. If im not mistaken,
the only issue you have is: You wrote reciever inside your manifest instead of receiver.
So the BroadcastReceiver never got registered correctly.
To the topic of registering in code:
Yeah thats possible. Just create an instance of your receiver
and use Context.registerReceiver(mReceiver, new IntentFilter(...)).
If you have registered in your manifest, there is no need to do that.
BroadcastReceivers only live for the execution of onReceive(). Therefore
the system creates the instances and kills them afterwards.

Categories

Resources