How to get if an app requests a permission? - java

Good morning
I was searching for a way to know if an app, given the package name, requests a certain permission and if that permission is granted (via settings). I was looking for something like that:
if(//com.package.name requests Manifest.permission.camera and that permission is granted)
{//do something}
I have already read this thread http://stackoverflow.com/questions/31535088/android-m-programmatically-revoke-permissions but it doesn't find a way to know if an app is actually requesting a certain permission and if it's granted.
Thanks in advance
Regards

Use the following code in your activity:
I created StringBuffer appNameAndPermissions = new StringBuffer(); to append all the apps and permisssions info.
It's working fine. I tested it already. If you have any issues, please let me know.
StringBuffer appNameAndPermissions = new StringBuffer();
PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : packages) {
Log.d("test", "App: " + applicationInfo.name + " Package: " + applicationInfo.packageName);
try {
PackageInfo packageInfo = pm.getPackageInfo(applicationInfo.packageName, PackageManager.GET_PERMISSIONS);
appNameAndPermissions.append(packageInfo.packageName+"*******:\n");
//Get Permissions
String[] requestedPermissions = packageInfo.requestedPermissions;
if(requestedPermissions != null) {
for (int i = 0; i < requestedPermissions.length; i++) {
Log.d("test", requestedPermissions[i]);
appNameAndPermissions.append(requestedPermissions[i]+"\n");
}
appNameAndPermissions.append("\n");
} catch (NameNotFoundException e) {
e.printStackTrace();
}
Use the following permission in your AndroidManifest.xml file:
<uses-permission android:name="android.permission.GET_TASKS"/>
Source and more answers here

Related

Why can't I write to Android External Storage?

I am trying to write an Android App that, among other things, needs to read and write files to "external" storage.
While I am able to browse and select a folder on external storage, every time I try to access the file, I get a Permission denied I/O exception.
I HAVE included the following permissions in my app's manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
I have also enabled the STORAGE permission for the app in Android.
I am developing on a Chromebook, so I do not have access to emulators. So I test and debug my app on my phone (a Pixel 3), via a USB-C cable. I can also generate an APK and sideload it on my Chromebook, but I can not debug this way.
The following code sample was one I gathered from the Internet.
public void writeFileExternalStorage(View view) {
String cashback = "Get 2% cashback on all purchases from xyz \n Get 10% cashback on travel from dhhs shop";
String state = Environment.getExternalStorageState();
//external storage availability check
if (!Environment.MEDIA_MOUNTED.equals(state)) {
return;
}
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), filenameExternal);
FileOutputStream outputStream = null;
try {
file.createNewFile();
//second argument of FileOutputStream constructor indicates whether to append or create new file if one exists
outputStream = new FileOutputStream(file, true);
outputStream.write(cashback.getBytes());
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
When the file.createNewFile() is executed, The following exception is thrown: java.io.IOException: Permission denied
I have been banging my head against the wall for two days on this issue, and it's not doing any good. I hope someone here can help, as my head really hurts! :-)
Apparently, Android 10 is to blame.
I lowered the Target SDK to 28 (Android 9) and the code works.
It looks like if I want this to work for Android 10, I will have to use MediaStore for SDK 29+.
you have to check for runtime permission before writeFileExternalStorage function :
private static final int WRITE_EXTERNAL_STORAGE = 0;
private static final int REQUEST_PERMISSION = 0;
int permissionCheckStorage = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheckStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_PERMISSION);
return;
}

How to put multiple assets in a data event for Android Development

I am trying to make an app that sends files from my Android Watch to my Android Phone.
The problem I have is that if I record and save multiple files and send all of them at the same time, I do not get all the files back on the phone side. I only receive one file.
The code for sending the file is as follows. This code is implemented on the Watch side.:
public void sendData(View v){
String fname = "_Activity.bin";
int FileCounterCopy = FileCounter;
if(mGoogleApiClient.isConnected()){
for (int i = 0; i < FileCounterCopy ; i++){
String FileName = String.valueOf(i) + fname;
File dataFile = new File(Environment.getExternalStorageDirectory(), FileName);
Log.i("Path", Environment.getExternalStorageDirectory().toString());
Log.i("file", dataFile.toString());
Asset dataAsset = createAssetfromBin(dataFile);
sensorData = PutDataMapRequest.create(SENSOR_DATA_PATH);
sensorData.getDataMap().putAsset("File", dataAsset);
PutDataRequest request = sensorData.asPutDataRequest();
Wearable.DataApi.putDataItem(mGoogleApiClient, request).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(DataApi.DataItemResult dataItemResult) {
Log.e("SENDING IMAGE WAS SUCCESSFUL: ", String.valueOf(dataItemResult.getStatus().isSuccess()));
}
});
boolean deleted = dataFile.delete();
Log.i("Deleted", String.valueOf(deleted));
FileCounter--;
}
mTextView.setText(String.valueOf(FileCounter));
Return();
}
else {
Log.d("Not", "Connecteddddddddd");
}
}
The code for receiving the files is as follows and is implemented on the phone side.
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
Counter++;
final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
dataEvents.close();
Log.e("List Size: ", String.valueOf(events.size()));
for (DataEvent event : events) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
Log.v("Data is changed", "========================");
String path = event.getDataItem().getUri().getPath();
if (SENSOR_DATA_PATH.equals(path)) {
DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
fileAsset = dataMapItem.getDataMap().getAsset("File");
myRunnable = createRunnable();
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
new Thread(myRunnable).start();
}
}
}
status.setText("Received" + " File_"+ String.valueOf(Counter) );
}
Right before the for loop, I check the size of the event and it only shows a size of 1, no matter how many files I save.
I am stuck on how to implement this (tbh I used code from youtube video/online resources so I am not 100% sure on how some of the api works).
Thanks in advance!
You're putting all of the files at the same path, with nothing to differentiate them - so each one you put in overwrites the previous ones. The Data API works much like a filesystem in this regard.
In your sendData method, you need code something like this:
sensorData = PutDataMapRequest.create(SENSOR_DATA_PATH + '/' + dataFile.toString());
And then in onDataChanged, either only check the path prefix...
if (path.startsWith(SENSOR_DATA_PATH)) {
...or, preferably, put the value of SENSOR_DATA_PATH in your manifest declaration as an android:pathPrefix element in the intent-filter of your data receiver. You can then remove the path check from your Java code completely. Docs for that are here: https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService
One other thing: it's good practice to clear stuff like these files out of the Data API when you're done using them, so that they're not taking up space there.

Retrieving Permission Description Returns 'null'

In order to get the description of a permission. I used the following code:
PackageManager packageManager = this.getPackageManager();
long time = System.currentTimeMillis();
PermissionInfo pinfo = null;
try {
pinfo = packageManager.getPermissionInfo("android.permission.BODY_SENSORS", PackageManager.GET_META_DATA);
if(pinfo != null) Log.i("permissions","pInfo not null???????????????????????????????????????");
Log.i("permissions ", pinfo.loadDescription(packageManager) + " *** " + pinfo.group);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
time = System.currentTimeMillis() - time;
But for some permissions, like- android.permission.BATTERY_STATS, I have a null char sequence when I call pinfo.loadDescription(packageManager). I don't understand why? And I'm trying to find the reason, but no way to get it. Any android expert could please explain it for me?
I have a null CharSequence when I call pinfo.loadDescription(packageManager).I don't understand why?
Because Google elected not to provide a description (or a title) for that permission. This is true for many of the signature-level permissions. You can examine the AOSP edition of the framework manifest to get a sense of what you can expect.

How to programatically clear application cache in Android 4.2.2 and above

In Android 4.0 I use this solution to clear my application cache and it works perfectly:
public void clearApplicationData()
{
File cache = getCacheDir();
File appDir = new File(cache.getParent());
if (appDir.exists()) {
String[] children = appDir.list();
for (String s : children) {
if (!s.equals("lib")) {
deleteDir(new File(appDir, s));
}
}
}
}
public static boolean deleteDir(File dir)
{
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
Unfortunately, this solution doesn't work in 4.2.2 Android version (and probably in above Android versions too). Anybody knows why? Maybe there is another method to clear cache?
Particulary I am interested in google map cache clearing and solution written above works for me in Android 4.0 but not in Android 4.2.2. Any help would be appreciated.
I don't get any errors in logcat. Device: Samsung Galaxy Tab 2 7.0'
I'm writing this as an answer because my comment will probably get buried. Even I had trouble clearing cache in a 4.2.2 device this code by David Wasser in this post worked for me.
PackageManager pm = getPackageManager();
// Get all methods on the PackageManager
Method[] methods = pm.getClass().getDeclaredMethods();
for (Method m : methods) {
if (m.getName().equals("freeStorage")) {
try {
long desiredFreeStorage = 8 * 1024 * 1024 * 1024;
m.invoke(pm, desiredFreeStorage , null);
} catch (Exception e) {
// Method invocation failed. Could be a permission problem
}
break;
}
}

Connecting to PC to view shared folders from Android device

I am working on a samba client for Android. Given an IP address it should connect to it and browse the shared folders.
For this I use JCIFS. I dropped the jar in my Android project and added following code to connect to PC and get the list of files:
private void connectToPC() throws IOException {
String ip = "x.x.x.x";
String user = Constants.username + ":" + Constants.password;
String url = "smb://" + ip;
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(user);
SmbFile root= new SmbFile(url, auth);
String[] files = root.list();
for (String fileName : files) {
Log.d("GREC", "File: " + fileName);
}
}
And I get in return: jcifs.smb.SmbAuthException: Logon failure: unknown user name or bad password.
But the credentials are correct. I also tried with another samba client from the android market that uses JCIFS and it successfully connected to that ip, so obviously I am doing something wrong here but don't know what especially.
Any help is highly appreciated.
In the end I managed successfully to connect to PC. The issue turned out to be in the NtlmPasswordAuthentication(); constructor.
So, instead of this:
String user = Constants.username + ":" + Constants.password;
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(user);
I changed to this:
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("",
Constants.username, Constants.password);
I don't know why, perhaps it's because of ":" special character, perhaps because of Android, but passing an empty domain name, the user name, and password separately to the constructor, solved the issue.
Since some people will get to this topic if they got a similar problem with android and JCIFS,
these are other common problems when trying to make it work:
*Put the .jar specifically in /libs folder of your android project (not just via "build path")
*Be sure that your project has internet permission What permission do I need to access Internet from an android application?
*Also be sure that your JCIFS code is running in a separate thread from the UI (in other words, use AsyncTask class) how to use method in AsyncTask in android?
*Code:
protected String doInBackground(String... params) {
SmbFile[] domains;
String username = USERNAME;
String password = PASSWORD;
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("",
username, password);
try {
SmbFile sm = new SmbFile(SMB_URL, auth);
domains = sm.listFiles();
for (int i = 0; i < domains.length; i++) {
SmbFile[] servers = domains[i].listFiles();
for (int j = 0; j < servers.length; j++) {
Log.w(" Files ", "\t"+servers[j]);
}
}
} catch (SmbException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return "";
}
these were the problems i encounter while trying to make work JCIFS on android, hope to help anyone, regards.
maybe i can help other people too.
I had the problem that i used thread.run() instead of thread.start() to execute the Smb-Code in a Runnable. I searched a lot of time for an answer but nothing fixed my problem.
But then a friend explained me the different between thread.run() and thread.start():
run(): Execute the Methode (for example the run() Methode of a Runnable) like a normal Method (synchronous)
start(): Start the Thread with the Runnable in an own task (asynchronous)
And for Smb you need a asynchronous Thread. Because of this you need to call thread.start()!
Maybe someone make the same mistake as i did.

Categories

Resources