Based on the notification title which says "you have been logged out", I want to trigger clear app data event in android. I browsed a lot. didn't get what I needed. can someone help?
The Simplest way to do this is
private void deleteAppData() {
try {
// clearing app data
String packageName = getApplicationContext().getPackageName();
Runtime runtime = Runtime.getRuntime();
runtime.exec("pm clear "+packageName);
} catch (Exception e) {
e.printStackTrace();
} }
This will clear the data and remove your app from memory. It is equivalent to clear data option under Settings --> Application Manager --> Your App --> Clear data
As an alternate I have one more option i.e. ((ActivityManager)context.getSystemService(ACTIVITY_SERVICE)) .clearApplicationUserData();
But it has a limitation that it only work API level >=19
Related
public void executeApp(ExecuteABCDEvent event) {
PackageManager pm = this.getContext().getPackageManager();
try {
String packageName = "package name here";
Intent launchIntent = pm.getLaunchIntentForPackage(packageName);
this.getContext().startActivity(launchIntent);
} catch (Exception e1) {
Log.d("Exception", e1.getMessage());
}
}
I am opening a 3rd pary application using the above code.
Along with opening of this 3rd party application I also want to populate some text fields.
Solution 1: put and get data from intent.
I cannot user solution 1 as i cannot use the get methods in 3rd party app.
Solution 2: Content provider.I am not sure how content provider of application works and how it helps.
Is there another approach for this.
You have no good way of doing what you want. For obvious security reasons, apps cannot hack into other apps.
You are welcome to create an AccessibilityService and attempt to use that to achieve your ends. I am skeptical that it will work, and even if it does, I am skeptical that many people will install your app, given the large security warnings that are presented when the user goes in to activate your AccessibilityService.
What i want to do is to update local database when an application is removed or added.
But when i got PACKAGE_REMOVED,I found it's unable to get its ApplicationInfo any more. It just throws namenotfound exception.Any suggestions?thanks.
if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
try{
final String packageName = intent.getData().getSchemeSpecificPart();
ApplicationInfo app = pm.getApplicationInfo(packageName, 0);
final String fname = app.sourceDir;
String md5 = Util.Md5(fname);
dbm.deleteApk(md5);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The package has already been removed when the Intent PACKAGE_REMOVED is broadcast. At that point it is too late. You'll need to save the information you want BEFORE that. You can do that either when the package is installed, or you could have your application run on boot and collect the ApplicationInfo for all installed packages and save that that in a database or whatever. When the user deletes a package, you'll get the PACKAGE_REMOVED broadcast and you can find the information you want in your local database.
try:
pm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
public static final int GET_UNINSTALLED_PACKAGES
Added in API level 3
Flag parameter to retrieve some information about all applications (even uninstalled ones) which have data directories. This state could have resulted if applications have been deleted with flag DONT_DELETE_DATA with a possibility of being replaced or reinstalled in future.
Note: this flag may cause less information about currently installed applications to be returned.
My android application will be preinstalled. And I want to keep tracking of preinstalled apps.
For this purpose I need somehow to save a key or a flag (which means that app is preinstalled). I will add this key to each request to my back-end and will analyze it.
I have an issue with that. An issue is about update from Google Play.
The standart workflow is the following:
1) I give to a manufacturer a special version of my application, which saves a key somehow (in Shared Prefs for example).
2) Manufacturer sell device with the app (special, modified).
3) When User get it, there definetly be next version of the app (standart, without special code) in the Google Play, so user perhaps update it without any launching (the worst case).
4) I lost my tracking possibility. (new apk fully removing never launched old one which was special)
To solve it I was listening a system broadcast ON_BOOT_COMPLETE, but its not working properly on Android 3.1+.
Have you any ideas how can I do that?
Can you install an additional .apk that only has a service? Then that service can have the key, etc. and it can listen for when your app starts and send the tracking info. Then it won't matter if your app gets upgraded; the service will still be the same.
There are some ways to know if application is system application or not. Like by checking installed directory of application or check FLAG_SYSTEM for the application.
Method 1 : -
Check location of application
public static boolean applicationIsSystemApp(Context mContext, String packageName) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
String appLocation = applicationInfo.publicSourceDir;
// OR String appLocation = applicationInfo.sourceDir;
// Both returns the same
// if package is pre-installed then output will be /system/app/application_name.apk
// if package is installed by user then output will be /data/app/application_name.apk
// Check if package is system app
if (appLocation != null && appLocation.startsWith("/system/app/")) {
return true;
}
} catch (NameNotFoundException e) {
e.printStackTrace(); // TODO Can handle as your logic
}
return false;
}
Method 2 : -
Check FLAG_SYSTEM of application
public static boolean applicationIsSystemApp(Context mContext, String packageName) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
// FLAG_SYSTEM is only set to system applications,
// this will work even if application is installed in external storage
// Check if package is system app
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return true;
}
} catch (NameNotFoundException e) {
e.printStackTrace(); // TODO Can handle as your logic
}
return false;
}
And call this method as
if (applicationIsSystemApp(getApplicationContext(), "com.example.mysystemapp")) {
// Application is system app
} else {
// Application has been installed as 3rd Party app
}
There is a property sourceDir in ApplicationInfo class. You can use it to distinguish the system app version and the upgraded one.
System app will start with "/system/app" and upgraded app will start with "/data/app"
Try something like this
try {
ApplicationInfo appInfo = this.getPackageManager().getApplicationInfo("com.example.san", 0);
boolean isSystemApp = false;
if(appInfo.sourceDir.startsWith("/system/app")){ // You can use "contains" too
isSystemApp = true;
}
} catch (Exception e) {
e.printStackTrace();
}
Note: I didnt test it.. Hope it works
One proven solution is to pre-install an APK that on have the permission: RECEIVE_BOOT_COMPLETED
Then on the very first boot - you make a quick notation that you are a PREINSTALLED to whatever persistent storage you use, preferably add a token file.
You look for this token file on all your later APK versions to determine if the running copy originates from a device which had it pre-installed or not.
This solves the mayor issues:
1) Then its OK if the user updates you APK to the latest version, you can still read this token.
2) You don't have to maintain a separate APK on google play for the pre-installed community
3) You don't have to hustle with the OEM to install multiple APK when you actually only have one App.
I noticed that some running services have a Settings rather than Stop button in the details page of Running services in the system Settings app. I want to setup my own service to work like this.
After digging into the source code of Settings app, I found a clue:
ActivityManager.getRunningServiceControlPanel()
Returns a PendingIntent you can start to show a control panel for the given running service. If the service does not have a control panel, null is returned.
My question is: how can I set a control panel for my own service?
In case anyone's curious, I found the code behind this feature. The service's description and configuration intent can be set during a service binding, if and only if the caller is running as SYSTEM.
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2.1_r1/com/android/server/am/ActivityManagerService.java#11651
int clientLabel = 0;
PendingIntent clientIntent = null;
if (callerApp.info.uid == Process.SYSTEM_UID) {
// Hacky kind of thing -- allow system stuff to tell us
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
try {
clientIntent = (PendingIntent)service.getParcelableExtra(
Intent.EXTRA_CLIENT_INTENT);
} catch (RuntimeException e) {
}
if (clientIntent != null) {
clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
if (clientLabel != 0) {
// There are no useful extras in the intent, trash them.
// System code calling with this stuff just needs to know
// this will happen.
service = service.cloneFilter();
}
}
}
This code was moved at some point, but still exists in KitKat, unchanged.
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/com/android/server/am/ActiveServices.java#665
on Android phones, under Call -> Additional settings -> Caller ID
it is possible to hide your caller ID. I want to do that programatically from my code, but was not able to find a way to do that.
I searched through
android.provider
android.telephony
for 2.1 release and was not able to find it.
Has anybody successfully solved this issue?
Thanks in advance. Best regards.
Here I will describe two approaches I tried.
1.) It is possible to display Additional Call Settings screen from your application. Although it looks like it is part of the Settings application, that is not true. This Activity is part of the Native Phone Application, and it may be approached with the following intent:
Intent additionalCallSettingsIntent = new Intent("android.intent.action.MAIN");
ComponentName distantActivity = new ComponentName("com.android.phone", "com.android.phone.GsmUmtsAdditionalCallOptions");
additionalCallSettingsIntent.setComponent(distantActivity);
startActivity(additionalCallSettingsIntent);
Then user has to manually press on the CallerID preference and gets radio button with 3 options.
This was not actually what I wanted to achieve when I asked this question. I wanted to avoid step where user has to select any further options.
2.) When approach described under 1.) is executed in the Native Phone Application, function setOutgoingCallerIdDisplay() from com.android.internal.telephony.Phone has been used.
This was the basis for the next approach: use Java Reflection on this class and try to invoke the function with appropriate parameters:
try
{
Class <?> phoneFactoryClass = Class.forName("com.android.internal.telephony.PhoneFactory");
try
{
Method getDefaultPhoneMethod = phoneFactoryClass.getDeclaredMethod("getDefaultPhone");
Method makeDefaultPhoneMethod = phoneFactoryClass.getMethod("makeDefaultPhone" , Context.class);
try
{
makeDefaultPhoneMethod.invoke(null, this);
Object defaultPhone = getDefaultPhoneMethod.invoke(null);
Class <?> phoneInterface = Class.forName("com.android.internal.telephony.Phone");
Method getPhoneServiceMethod = phoneInterface.getMethod("setOutgoingCallerIdDisplay", int.class, Message.class);
getPhoneServiceMethod.invoke(defaultPhone, 1, null);
}
catch (InvocationTargetException ex)
{
ex.printStackTrace();
}
catch (IllegalAccessException ex)
{
ex.printStackTrace();
}
}
catch (NoSuchMethodException ex)
{
ex.printStackTrace();
}
}
catch (ClassNotFoundException ex)
{
ex.printStackTrace();
}
Firstly I tried just to use getDefaultPhone(), but I get RuntimeException
"PhoneFactory.getDefaultPhone must be called from Looper thread"
Obviously, issue lies in the fact that I tried to call this method from the Message Loop that was not the Native Phone App one.
Tried to avoid this by making own default phone, but this was a security violation:
ERROR/AndroidRuntime(2338): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.provider.Telephony.SPN_STRINGS_UPDATED from pid=2338, uid=10048
The only way to overcome (both of) this would be to sign your app with the same key as the core systems app, as described under
Run secure API calls as root, android
I'm not sure if this is a global feature, but Australian phones can hide their number by prefixing the caller's number with #31# or 1831. This may not be the perfect solution, but a prefix like this could possibly work for your requirements during coding.