Code:
void clearCache() {
if (mClearCacheObserver == null) {
mClearCacheObserver = new CachePackageDataObserver();
}
PackageManager mPM = getPackageManager();
#SuppressWarnings("rawtypes")
final Class[] classes = {Long.TYPE, IPackageDataObserver.class};
Long localLong = Long.valueOf(CACHE_APP);
try {
Method localMethod =
mPM.getClass().getMethod("freeStorageAndNotify", classes);
localMethod.setAccessible(true);
// Start of inner try-catch block
try {
localMethod.invoke(mPM, localLong, mClearCacheObserver);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.getCause().printStackTrace();
}
// End of inner try-catch block
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
}
Logcat:
java.lang.SecurityException: Neither user 10206 nor current process has android.permission.CLEAR_APP_CACHE.
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.content.pm.IPackageManager$Stub$Proxy.freeStorageAndNotify(IPackageManager.java:5081)
at android.app.ApplicationPackageManager.freeStorageAndNotify(ApplicationPackageManager.java:2500)
at android.content.pm.PackageManager.freeStorageAndNotify(PackageManager.java:4710)
at java.lang.reflect.Method.invoke(Native Method)
at com.onexsoftech.clearcacheapp.MainActivity.clearCache(MainActivity.java:278)
at com.onexsoftech.clearcacheapp.MainActivity.insertDummyContactWrapper1(MainActivity.java:495)
at com.onexsoftech.clearcacheapp.MainActivity.insertDummyContact(MainActivity.java:472)
Prior to Android 6.0, CLEAR_APP_CACHE had a protectionLevel of dangerous, so ordinary SDK apps could request it in the manifest.
As of Android 6.0, CLEAR_APP_CACHE has a protectionLevel of signature|privileged. Ordinary Android apps cannot hold this permission. You can only hold this permission if your app is signed with the firmware's signing key or you are installed on the privileged system partition.
From Android M -> CLEAR_APP_CACHE, Protection level: system|signature
Android 6.0 does not change the behavior of normal permissions (all
non-dangerous permissions including normal, system, and signature
permissions).
So it is not possible to ask for that permission in runtime. To be more precise
A signature|system permission, meaning that it can only be held by
apps that are signed with the firmware's signing key or are installed
on the system partition (e.g., by a rooted device user). From this stackoverflow Q/A.
Docs:
https://source.android.com/devices/tech/config/runtime_perms.html#affected-permissions
Add Permission in AndroidManifest.xml
<permission android:name="android.permission.CLEAR_APP_CACHE"/>
<uses-permission android:name="android.permission.CLEAR_APP_CACHE"/>
Make a Constant for Request Code.
Constants.java
public static final int REQUEST_CODE_FOR_PERMISSION = 501;
Request Permission :-
public static void requestPermissionForClearCache(Activity activity) {
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CLEAR_APP_CACHE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CLEAR_APP_CACHE)) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CLEAR_APP_CACHE}, Constatnts.REQUEST_CODE_FOR_PERMISSION);
} else {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CLEAR_APP_CACHE}, Constatnts.REQUEST_CODE_FOR_PERMISSION);
}
}
}
Override Below method in Fragment.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == Constatnts.REQUEST_CODE_FOR_PERMISSION && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted successfully
} else {
// permission was NOT granted successfully
}
}
Related
I can't find in the doc how to retrieve if device is configured as a portable hotspot.
I've read How to detect if a network is (configured as) a mobile hotspot on Android? but I don't know if the feature has been implemented?
You can use below code to check if Tethering is enabled or not on your device:
private static Method isWifiApEnabledMethod;
public static boolean isWifiApEnabled(WifiManager wifiManager) {
if (isWifiApEnabledMethod == null) {
try {
isWifiApEnabledMethod = wifiManager.getClass().getDeclaredMethod("isWifiApEnabled");
isWifiApEnabledMethod.setAccessible(true); //in the case of visibility change in future APIs
} catch (NoSuchMethodException e) {
Log.w(TAG, "Can't get method by reflection", e);
}
}
if (isWifiApEnabledMethod != null) {
try {
return (Boolean) isWifiApEnabledMethod.invoke(wifiManager);
} catch (IllegalAccessException e) {
Log.e(TAG, "Can't invoke method by reflection", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "Can't invoke method by reflection", e);
}
}
return false;
}
Don't forget to add below permission in AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
For the SO link mentioned above in question:
This feature is not available i.e. has not been implemented.
For more information check this link where Google officially marked the status as Status: Won't Fix (Obsolete)
Hope this will help you. Thanks!
Is there anyway in android sdk where they provide an information for specific permission? Like how google play does, whenever you click on a permission you are able to read what does this permission do. I have this function to return me specific permissions for an application
public static List<String> getAppPermissions(Context context, String packageName) {
try {
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
return Arrays.asList(info.requestedPermissions);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
By this code im getting only permission names, but I'm wondering if there is any such api that return permissions and their details.
to answer my question, PermissionInfo is actually the right class to get a description about any android permission for example:
#Nullable
public static PermissionInfo getPermissionInfo(#NonNull Context context, #NonNull String permission) {
try {
return context.getPackageManager().getPermissionInfo(permission, PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
above method will return PermissionInfo instance if it could parse the permission name given to it, and then simply you could call loadDescription to load the permission description.
I'm try send DTMF codes in icoming CALL. For this i'n try use Java reflection:
public void initialize(){
ClassLoader classLoader = Dtmf.class.getClassLoader();
final Class<?> classCallManager = classLoader.loadClass("com.android.internal.telephony.CallManager");
Method methodGetInstance = classCallManager.getDeclaredMethod("getInstance");
objectCallManager = methodGetInstance.invoke(null);
methodGetState = classCallManager.getDeclaredMethod(SEND_DTMF, char.class);
}
public boolean sendDtmf(char ch) {
boolean result = false;
if ( methodGetState != null) {
try {
Object res = methodGetState.invoke(objectCallManager,
new Object[]{Character.valueOf(ch)});
if (res instanceof Boolean) {
result = ((Boolean) res).booleanValue();
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
return result;
}
Link for source code of class CallManager : Call Manager source code
But i'm always get "false" in method sendDtmf(). In debug, code is go into next:
Object res = methodGetState.invoke(objectCallManager,
new Object[]{Character.valueOf(ch)});
What wrong?
The method is likely throwing an InvocationTargetException if your application isn't signed with the platform certificate as conventional apps cannot execute these methods (and will not be granted the required platform permissions to do so).
In short: the method is returning false because you're catching (and ignoring) the exception.
There's an open issue (#1428) on the Android issue tracker for sending DTMF tones as it presently isn't possible.
bit of a strange question.
I'm trying to write some code that, for testing purposes, allows my test instance of Instrumentation to programmatically add Call Logs. It is simple but to do this, but it requires the android.permission.WRITE_CALL_LOG permission.
I've added this in my manifest
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
But when I use this code during runtime...
PackageManager instrumentationPM = instrumentationContext.getPackageManager();
PackageInfo info = instrumentationPM.getPackageInfo(PACKAGE_NAME,
PackageManager.GET_PERMISSIONS);
PermissionInfo[] permission_info = info.permissions;
The permission_info (aka info.permissions) array is null. Thus, during runtime no permissions are detected. Any clue what could be the issue here, and if this is at all relevant to my task of allowing my Instrumentation to add call logs?
Thanks a bunch.
This code will not return the <uses-permission> specified manifest file. Instead it will return the <permission>, which is system level permission.
I tried this code:
PackageManager instrumentationPM = getApplicationContext().getPackageManager();
PackageInfo info;
try {
info = instrumentationPM.getPackageInfo("com.example.testingproj",
PackageManager.GET_PERMISSIONS);
PermissionInfo[] permission_info = info.permissions;
if(permission_info!=null)
System.out.println(permission_info.length);
} catch (NameNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
And I have kept this permission in my manifest file:
<permission android:name="anypermission"></permission>
It gives me length = 1 in logcat.
I am not aware of getting all the <uses-permission> from manifest. But if you just want to check if there is a specific permission in manifest, you can try this:
if (instrumentationPM.checkPermission(permission.ACCESS_WIFI_STATE, getPackageName()) == PackageManager.PERMISSION_GRANTED) {
System.out.println("wifi state permission");
} else {
// do something
}
code snippet
void takeSnapShot()
{
Process process = null;
try
{
process = Runtime.getRuntime().exec("/system/bin/screencap -p /sdcard/snapshot/test_2.png" );
try
{
process.waitFor();
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am gettin an empty file saved whereas If i use the same command through adb shell, i get my screen captured.
Any help will be appreciatable
Edit: my previous answer was mistaken, any app can use the screen capture command.
It might be a permission issue. Are you sure you have permission to write to sdcard?
Check this post, which covers your topic:
How to run android system app without root permisson?
I solved this by adding the following permission to my Manifest.
<uses-permission
android:name="android.permission.READ_FRAME_BUFFER"
tools:ignore="ProtectedPermissions"/>
NOTE: This is a protected permission, my application is a system app and also signed using the platform key.