Can we clear or delete data of one application from another application in android. If it is not possible simply could you please suggest any tricky way to do this like to go to the folder in internal memory and delete that folder programatically.
Thanks.
Simple answer,
Android is designed that this should not be possible.
But when using root access you can actually delete folders from other applications.
I believe if two applications having a different package, but with the same signature, actually can have access to each others private folders. Or i'm not sure, i believe you could add some kind of declaration to you manifest file allowing other (friend) apps to have access to your private folder. But i'm not sure i should search for it.
Edit after search:
Apps having the same android:sharedUserId and android:sharedUserLabel and signature have access to each others private files.
http://developer.android.com/guide/topics/manifest/manifest-element.html#uid
Two Android applications with the same user ID
Edit 2:
There are some private methods in the android API, witch can be used to clear app data i think. I'm not sure but if you reflect those methods with the right permissions in you manifest file it could be possible to clear app data, but i'm not 100% sure.
Some small example code:
Method clearApplicationUserData = getReflectedMethod("clearApplicationUserData", String.class, IPackageDataObserver.class);
And the method i use the get it reflected...
private Method getReflectedMethod(String methodname, Class<?>... args) {
Method temp = null;
try {
temp = pm.getClass().getMethod(methodname, args);
} catch (SecurityException e) {
return null;
} catch (NoSuchMethodException e) {
return null;
}
return temp;
}
The IPackageDataObserver class should be copied from the original android source, and added as new class in the source folder of your project under the package android.content.pm.
When you want to clear user data i think you should invoke the method like this:
public void clearApplicationUserData(String packageName) {
if (clearApplicationUserData != null) {
try {
clearApplicationUserData.invoke(pm, packageName, data_helper);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
}
The data_helper is any class extending the IPackageDataObserver.Stub class.
You can find a lot of questions about reflecting methods and stuff here on stackoverflow.
I have no idea if this works but this is the only way i can think of.
Rolf
If its stored in the database you can delete the data using content provider by following method
mRowsDeleted = getContentResolver().delete(
UserDictionary.Words.CONTENT_URI, // the user dictionary content URI
mSelectionClause // the column to select on
mSelectionArgs // the value to compare to
);
follow the methods Here
The question is not very clear.
Do you mean your app will delete data from someone elses app? The answer there is "it depends". First, if the data is on the SD card, you could access it and delete it. If the data is in the apps private data area, then you cannot do that unless your phone is rooted.
If the apps in question are both made by you, the answer is yes, it is possible. You would have to use the android:sharedUserId property in the manifest file of each app, make them the same and sign both apps with the same key. This would give the apps access to each others data.
If the data you are speaking of is on the devices SD card, yes you can. If it is in the internal storage, then no (unless you created both apps and have used the
Related
I am in the process of implementing access to a SQLite database via SQLCipher in my hybrid Cordova app for Android which uses one custom plugin (i.e. written by me). The SQLCipher documentation - as well as other tutorials on using SQLite in Android - keep referring to Context.getDatabasePath. In my plugin code I store other app files and make extensive use of Context.getFilesDir. In what way is getDatabasePath different from getFilesDir. For instance, does it promise a better chance that the database will persist and not somehow get dumped because the OS decides to create "some more room" by deleting some files stored in Context.getFilesDir?
Both are resolved to the same directory. getDatabasePath calls getDatabasesDir.
getDatabasesDir:
private File getDatabasesDir() {
synchronized (mSync) {
if (mDatabasesDir == null) {
if ("android".equals(getPackageName())) {
mDatabasesDir = new File("/data/system");
} else {
mDatabasesDir = new File(getDataDir(), "databases");
}
}
return ensurePrivateDirExists(mDatabasesDir);
}
}
getFilesDir:
#Override
public File getFilesDir() {
synchronized (mSync) {
if (mFilesDir == null) {
mFilesDir = new File(getDataDir(), "files");
}
return ensurePrivateDirExists(mFilesDir);
}
}
Notice the returned File is resolved by ensurePrivateDirExists in both method, which has the same input directory resolved by getDataDir.
getDataDir
Returns the absolute path to the directory on the filesystem where all
private files belonging to this app are stored.
So, there is NO difference in your case.
Do not forget the returned path can change, as the doc says:
The returned path may change over time if the calling app is moved to
an adopted storage device, so only relative paths should be persisted.
I'm working on an app built using Firebase on Android. The application is for keeping track of in-patients currently under our care. Our team can enter progress notes for each patient, and add tasks needed yo be performed for each patient, and mark them when they're done. I have all that done, however, I need to add one more option, where I can select a patient, and export the current view (with all the many-to-one data associated with the main record) to an external file (editable file), so we may use it to write his/her final report and summary. I've searched online, and found many recommending to export the view as a bitmap, then to pdf ... but that makes the document un-editable .. If someone has any ideas, or can point me to the right direction, I'd be grateful. The final format is not really an issue ... pdf, txt, doc, html .... I guess it doesn't really matter, as long as the data can be exported as it is in the current view (ordered and making sense), and can be edited.
Any help will be appreciated. Thank you.
I once made an app with the option to export data to a txt file on the device storage. Here's the method I used:
public void exportTxt(String text){
if(Environment.getExternalStorageState().equalsIgnoreCase("mounted"))//Check if Device Storage is present
{
try {
File root = new File(Environment.getExternalStorageDirectory(), "MyAppFolder");//You might want to change this to the name of your app. (This is a folder that will be created to store all of your txt files)
if (!root.exists()) {
root.mkdirs();
}
File myTxt = new File(root, "filename.txt"); //You might want to change the filename
FileWriter writer = new FileWriter(myTxt);
writer.append(text);//Writing the text
writer.flush();
writer.close();
Toast.makeText(this, "File exported", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
else
Toast.makeText(this, "Can't access device storage!", Toast.LENGTH_SHORT).show();
}
Don't forget to add this permission to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
So in order to use this method, all you need to do is group all of your currentView data on a single String and pass it as a parameter.
I am creating a framework to be used by many departments in my work environment. I need a way to dynamically load classes into the framework from individual department apk's. For instance a way to dynamically load department A's content provider class into the framework.
I have had little luck trying to figure this out, any help would be much appreciated. Thanks.
If you want to load an already known class from another .apk currently installed on your device you can take the following approach (assuming your class has a default constructor). Also please remember that you must know the package name of the other .apk file and the other .apk file's package name must be different from your applications package name.
private Object loadClass(String packageName, String className){
Object plugin = null;
try {
PackageManager packageManager = getPackageManager();
ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
DexFile df = new DexFile(appInfo.sourceDir);
ClassLoader cl = getClassLoader();
Class classToInvestigate = df.loadClass(className, cl);
plugin = classToInvestigate.newInstance();
} catch (Exception e) {
System.out.println("EXCEPTION");
}
finally{
return plugin;
}
}
I expect it would be a security hole if this was allowed and your design is risky as you are tightly coupling your program to someone else's.
A better solution is to be able to just use the content provider from your activity, much as you can access the contacts in Android.
My app has .txt files in subdirectories in the assets folder. It reads those .txt files and puts them in a textview. It's working great and no problems.
Should I be concerned about the files in the assets folder getting deleted by the user or missing. If this ever could happen, my app would get an error because the file would not be there when it tried to read it into the stream.
Is there a need for me to check the existence of an asset file before I read it or does the asset manager take care of it all? I also was wondering if there's a chance that a user would or could delete and asset file.
Like I say, everything works fine without me inserting code to check for file existence. I just wondered if people use the .exists() statement every time they go to read in a stream from assets.
You may be concerned that the file have been removed and the apk resigned
You can check using:
Arrays.asList(getResources().getAssets().list("")).contains("myFile")
if you really want to check for the file existence:
AssetManager mg = getResources().getAssets();
InputStream is = null;
try {
is = mg.open(pathInAssets);
//File exists so do something with it
} catch (IOException ex) {
//file does not exist
} finally {
if (is != null) {
is.close();
}
}
If your file is located in assets/folder/file.ext, then pathInAssets would be
"folder/file.ext"
Ideally after apk is built, nobody can remove any assets from it, but if someone decompiled it and recompiles than it may be possible.
Though for other scenarios also when an asset is not present in apk at Runtime, we can check the existence of asset.
In our app, we have a provision to build app using gradle, ant and eclipse, and for each build mechanism some of our assets file are bundled in apk and some are not, so to identify if any asset file is present in current build apk at runtime,
we do this as follows:
private boolean isAssetExists(String pathInAssetsDir){
AssetManager assetManager = AppContext.get().getResources().getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open(pathInAssetsDir);
if(null != inputStream ) {
return true;
}
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
Yes and No.
A normal user would not be able to delete them, but a user on a rooted phone who doesn't know what they're doing… that's a different situation.
If you ask me, the extra code is not needed. Also if you try and open a file that doesn't exist, you will get an exception thrown at some point, catch that and display a dialog if you really want to.
AssetManager am = getAssets();
try {
List<String> mapList = Arrays.asList(am.list("path/in/assets/folder"));
if (mapList.contains("file_to_check")) {
Log.e("ERROR", "exists");
} else {
Log.e("ERROR", "not exists");
}
} catch ( IOException ex){
ex.printStackTrace();
}
Convert to function or method can be easy ;)
I think you should be OK. From having a root around in my phone I can't see any way of deleting the assests without deleting the app as it all seems to be wrapped up in the .apk file. You can do it but I think you need to be rooted or use adb.
I would personally surround any reading/writing with a try/catch block anyway, just to be safe.
In Android, how do I get the application's id programatically (or by some other method), and how can I communicate with other applications using that id?
If your are looking for the value defined by applicationId in gradle, you can simply use
BuildConfig.APPLICATION_ID
EDIT 2022:
As indicated in the comments, BuildConfig.APPLICATION_ID is deprecated, but for librairies only. In this case, BuildConfig.LIBRARY_PACKAGE_NAME should be used instead, as explained here.
Also, now, Context::getPackageName returns the value defined by applicationId in gradle, even if you have several flavors with different applicationId (with a unique namespace), see here.
If by application id, you're referring to package name, you can use the method Context::getPackageName (http://http://developer.android.com/reference/android/content/Context.html#getPackageName%28%29).
In case you wish to communicate with other application, there are multiple ways:
Start an activity of another application and send data in the "Extras" of the "Intent"
Send a broadcast with specific action/category and send data in the extras
If you just need to share structured data, use content provider
If the other application needs to continuously run in the background, use Server and "bind" yourself to the service.
If you can elaborate your exact requirement, the community will be able to help you better.
i'm not sure what "application id" you are referring to, but for a unique identifier of your application you can use:
getApplication().getPackageName() method from your current activity
For getting AppId (or package name, how some says), just call this:
But be sure that you importing BuildConfig with your app id packages path
BuildConfig.APPLICATION_ID
Package name is your android app id .
String appId = BuildConfig.APPLICATION_ID
Or
https://play.google.com/store/apps/details?id=com.whatsapp
App Id = com.whatsapp
Else you can get id of process your application runs in:
final static int android.os.Process.myPid()
Returns the identifier of this process, which can be used with killProcess(int) and sendSignal(int, int).
I am not sure what you need the app/installation ID for, but you can review the existing possibilities in a great article from Android developers:
http://android-developers.blogspot.com/2011/03/identifying-app-installations.html
To sum up:
UUID.randomUUID() for creating id on the first time an app runs after installation and simple retrieval afterwards
TelephonyManager.getDeviceId() for actual device identifier
Settings.Secure.ANDROID_ID on relatively modern devices
Step 1: Open the Google Play Store
Step 2: Open any App in App Store
Example: facebook
Step 3: Click on any App and Look at the Browser link and At the End id=com.facebook.katana&hl=en will be there and this is your Apps Unique Id.
The PackageInfo.sharedUserId field will show the user Id assigned in the manifest.
If you want two applications to have the same userId, so they can see each other's data and run in the same process, then assign them the same userId in the manifest:
android:sharedUserId="string"
The two packages with the same sharedUserId need to have the same signature too.
I would also recommend reading here for a nudge in the right direction.
If the whole purpose is to communicate data with some other application, use Intent's sendBroadcast methods.
If you are using the new** Gradle build system then getPackageName will oddly return application Id, not package name. So MasterGaurav's answer is correct but he doesn't need to start off with ++
If by application id, you're referring to package name...
See more about the differences here.
** not so new at this point
++ I realize that his answer made perfect sense in 2011
Android App ES File Explorer shows the Android package name in the User Apps section which is useful for Bitwarden. Bitwarden refers to this as "android application package ID (or package name)".
To track installations, you could for example use a UUID as an identifier, and simply create a new one the first time an app runs after installation. Here is a sketch of a class named “Installation” with one static method Installation.id(Context context). You could imagine writing more installation-specific data into the INSTALLATION file.
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
Yon can see more at https://github.com/MShoaibAkram/Android-Unique-Application-ID
This is now deprecated you should use BuildConfig.LIBRARY_PACKAGE_NAME as answered here