Natalie Natalie - 7 months ago 88
Java Question

Getting the package name, common name, and icon from LAST INSTALLED app using BroadcastReceiver

I am trying to write a section of code that will allow me to get the common name, package name, and icon from the last installed app on my phone. Currently what I have is how to get the package name and common name from this source (get application name from package name), but this is not working for me.

The first error is "Cannot resolve method getApplicationContext and getPackageName". This makes sense because those methods are native to "Activity" and not "BroadcastReceiver" (I don't know how the other person got it to work).

So then I created a private context so that I could use getApplicationContext and getPackageName. My code now looks like what I have posted below, the gradle builds, but my app crashes when I install another app on my phone with the error:

can't instantiate class com.example.natalievold.applistener.NewInstallReceiver; no empty constructor


I read that I can solve this error by removing the "private context" section that I added, but I need that to use getApplicationContext and getPackageName. Does anyone know another way I can do this? I am also unsure of how to grab the icon of the last installed app.

public class NewInstallReceiver extends BroadcastReceiver
{

private Context mContext;

public NewInstallReceiver(Context context) {
mContext = context;
}


@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();

if(action.equals("android.intent.action.PACKAGE_ADDED")) {
Logger.getLogger("DATA:" + intent.getData().toString());
}
if(action.equals("android.intent.action.PACKAGE_REMOVED")){
Logger.getLogger("DATA:" + intent.getData().toString());
}
if(action.equals("android.intent.action.PACKAGE_REPLACED")){
Logger.getLogger("DATA:" + intent.getData().toString());
}



final PackageManager pm = mContext.getApplicationContext().getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo( this.mContext.getPackageName(), 0);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)");
}
}


My Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.natalievold.applistener">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">



<receiver android:name="com.example.natalievold.applistener.NewInstallReceiver">
<intent-filter android:priority="100">
<action
android:name="android.intent.action.PACKAGE_INSTALL"/>
<action
android:name="android.intent.action.PACKAGE_ADDED"/>
<action
android:name="android.intent.action.PACKAGE_DATA_CLEARED"/>
<action
android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>


<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


HERE IS THE FINAL CODE THAT I GOT TO WORK! (this is just the part for installing an app, not un-installing). And I didn't change anything in the manifest.

public class NewInstallReceiver extends BroadcastReceiver
{

@Override
public void onReceive(Context context, Intent intent) {

Log.d("NewInstallReceiver", "Intent: " + intent.getAction());


final PackageManager pm = context.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo( intent.getData().getSchemeSpecificPart(), 0);
Log.d("PACKAGE NAME","Intent" + ai);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)");
Log.d("Application NAME", "Intent: " + applicationName);

Drawable icon = context.getPackageManager().getApplicationIcon(ai);
Log.d("Application ICON", "Intent: " + icon);

}

}

Answer

I read that I can solve this error by removing the "private context" section that I added, but I need that to use getApplicationContext and getPackageName.

No, you do not.

Does anyone know another way I can do this?

First, use the Context that is passed in as the first parameter to your onReceive() method. That will allow you to replace this:

final PackageManager pm = mContext.getApplicationContext().getPackageManager();

with this:

final PackageManager pm = context.getPackageManager();

Second, getPackageName(), called on your own Context, gives you your package name. You would not appear to want your own package name. Instead, you want the package name of the app that was installed. To get that, call intent.getData().getSchemeSpecificPart(), to get the stuff after the package: scheme in the Uri of the Intent that was broadcast.

Then, to get at other information about that package, you can look it up in the PackageManager. Call getApplicationInfo() on the PackageManager, passing in the package name. This will give you an ApplicationInfo object. Pass that to getApplicationLabel() and getApplicationIcon() on PackageManager to get the label and icon, respectively.