createTempFile() on Android 10 permission denied - java

When attempting to create a temp file on Android 10 I am getting a permission denied error. Could someone please write a tutorial on how to create one in the external storage? Most are outdated and not for current versions of Android
Here is the logcat
2020-02-22 13:46:43.766 9544-9544/com.myapp.test E/MainActivity: Image file creation failed
java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:317)
at java.io.File.createTempFile(File.java:2018)
at com.myapp.test.MainActivity.create_image(MainActivity.java:915)
at com.myapp.test.MainActivity.access$200(MainActivity.java:85)
at com.myapp.test.MainActivity$6.onShowFileChooser(MainActivity.java:513)
at vo.runFileChooser(PG:10)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:336)
at android.os.Looper.loop(Looper.java:197)
at android.app.ActivityThread.main(ActivityThread.java:7762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
My AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:remove="android:maxSdkVersion" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
And code in the MainActivity.Java
private File create_image() throws IOException {
#SuppressLint("SimpleDateFormat")
String file_name = new SimpleDateFormat("yyyy_mm_ss").format(new Date());
String new_name = "file_"+file_name+"_";
File sd_directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(new_name, ".jpg", sd_directory); // fails due to permission denied
}

I was using official documentation to implement taking a photo from camera:
https://developer.android.com/training/camera/photobasics
yet it doesn't work and throws an exception on createTempFile method. Strangely google hasn't updated the code.
Here's a solution I've found:
Add:
android:requestLegacyExternalStorage="true"
to AndroidManifest.xml. No need to change anything in code. Works for now, but may not in upcoming Android versions.

You need to change
File sd_directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
to
File sd_directory = getExternalFilesDir(Environment.DIRECTORY_PICTURES);

You need to add a file provider
https://developer.android.com/reference/android/support/v4/content/FileProvider
And request the read/write storage permissions at runtime.
https://developer.android.com/training/permissions/requesting

In android 10 permission isn't directly accepted. So, you have ask from user to accept permission. There's a library which you can use for asking permission. Let me add that link
It is known as Dexter Library
You have to add a line to gradle.build
implementation 'com.karumi:dexter:6.2.2'
Following source code used for single permission at a time.
Dexter.withContext(this)
.withPermission(Manifest.permission.CAMERA)
.withListener(new PermissionListener() {
#Override public void onPermissionGranted(PermissionGrantedResponse response) {/* ... */}
#Override public void onPermissionDenied(PermissionDeniedResponse response) {/* ... */}
#Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {/* ... */}
}).check();
There's way to asking for multiple permission in Dexter library. You can get that on that link

As you are using getExternalStoragePublicDirectory In android 10+, you can't write on public folder directly. One way is to use getExternalFilesDir to capture image and then use MediaStore APIs to copy file into public directory.

Related

Reboot programmatically Android Things

I want to use this code in order to reboot my RPI3 running Android Things:
public static void Reboot()
{
try {
Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "reboot"});
proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
}
I get the following error:
java.io.IOException: Cannot run program "su": error=13, Permission denied
I add to the manifest all the permission
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
<uses-permission android:name="android.permission.SHUTDOWN"/>
Am I missing something?
/system/bin/reboot binary in DP 4, so as in all the previous dev previews, has world-executable permission, i.e. the following yields
adb shell ls -l /system/bin | grep reboot
-rwxr-xr-x 1 root shell ... reboot
That said, it is yet possible to execute the binary for any user (a.k.a app process in Android) without a need to grab su. Just execute in Java for
rebooting
Runtime.getRuntime().exec("reboot");
or for powering off
Runtime.getRuntime().exec("reboot -p");
No permission's needed in AndroidManifest.xml to run the binary successfully.
Caution: in case of security model changes in newer OS versions this approach may not work.
You can now do a reboot using:
https://developer.android.com/things/reference/com/google/android/things/devicemanagement/DeviceManager.html
Example
public class SomeActivity extends Activity {
void doReboot() {
DeviceManager.getInstance().reboot();
}
void doFactoryReset() {
boolean wipeExternalCard = true;
DeviceManager.getInstance().factoryReset(wipeExternalCard);
}
}
You need the com.google.android.things.permission.REBOOT permission
Access to system-protected features (such as those provided by the PowerManager.reboot() API) will be available to apps running on Android Things in a future developer preview release. You cannot (and should not) attempt to run your app process as the root user via su.
As a side note, the developer images for Android Things are built as userdebug, which means you can access root from the shell by simply rebooting the ADB daemon with the adb root command before you attempt to access the shell. This gives you any root access you may need during development without compromising the device security and allowing app processes to run as root.
You need a root access.
public static void runCmd(String cmd) {
DataOutputStream os;
try {
Process process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(cmd + "\n");
os.writeBytes("exit\n");
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Then you can run any commands that require root access like this: runCmd("reboot");

Permission Denial in android while working with camera

I am newbie to native android development. I am working on android studio. I have a tabbed activity in which i am using 2 tabs. In one tab there is a map with marker on gps location of the user. The second tab is to take picture and then to save it in the storage provided by the OS. For this i followed this tutorial, run the app on my device but it's crashes. I am running it on Marshmallow. Below is the error i get
java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=android/com.android.internal.app.ResolverActivity } from ProcessRecord{e8f9820 15070:com.example.accurat.faisal/u0a228} (pid=15070, uid=10228) with revoked permission android.permission.CAMERA
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3181)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1541)
at android.app.Activity.startActivityForResult(Activity.java:4298)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.support.v4.app.ActivityCompatJB.startActivityForResult(ActivityCompatJB.java:30)
at android.support.v4.app.ActivityCompat.startActivityForResult(ActivityCompat.java:146)
at android.support.v4.app.FragmentActivity.startActivityFromFragment(FragmentActivity.java:937)
at android.support.v4.app.FragmentActivity$HostCallbacks.onStartActivityFromFragment(FragmentActivity.java:1047)
at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:954)
at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:943)
at com.example.accurat.faisal.Camera$1.onClick(Camera.java:51)
at android.view.View.performClick(View.java:5716)
at android.widget.TextView.performClick(TextView.java:10926)
at android.view.View$PerformClick.run(View.java:22596)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
I searched it and found that i should ask permission for it so i followed this link and tried to add permission check like as bellow
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Check permission for CAMERA
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
// Callback onRequestPermissionsResult interceptado na Activity MainActivity
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.CAMERA},
MainActivity.REQUEST_CAMERA);
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE );
}
});
But i am getting red text of CAMERA and REQUEST_CAMERA. Though i have imported them as well but still the red text is showing
import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
Below is my manifest file
<uses-permission android:name="com.example.accurat.faisal.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.hardware.camera"/>
I don't know what is the problem and don't know the solution and i am stuck to it.
Any help would be highly appreciated
You need to add permission check in your code and based on user action of accecpt or denial should show the camera preview Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running. Also, you need to ask user permission for android.Manifest.permission.WRITE_EXTERNAL_STORAGE if you are creating a file which will be used as an input for image(captured via camera).

Android BLE: descriptor/characteristic write fails with GATT_WRITE_NOT_PERMITTED

From my mobile device(scanner) I am trying to write to a descriptor in a connected wearable(broadcaster).
on the wearable, I have defined the descriptor as
readCharacteristic = new BluetoothGattCharacteristic(Constants.READ_CHAR_UUID,
BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ);
readCharacteristic.addDescriptor(new BluetoothGattDescriptor(Constants.NOTIFY_DESC_UUID,
BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE));
on the mobile, I try to write to the characteristic with
BluetoothGattDescriptor descriptor = readCharacteristic.getDescriptor(Constants.NOTIFY_DESC_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
Unfortunately, this fails with status GATT_WRITE_NOT_PERMITTED in
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
}
In the wearable logcat I see gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT.
The same thing happens when I try to write to a characteristic.
What is weird is that the write succeeds when using an iOS scanner. This means that the wearable part is correct.
I have the permissions in the Manifest:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Devices used:
Nexus 5x 6.0.1 API 23,
Moto 360 5.1.1 API 22
Does anyone have an idea how to fix this descriptor/characteristic write issue?
From my mobile device(scanner) I am trying to write to a descriptor in
a connected wearable(broadcaster).
In this case it should be mobile device(central) and connected wearable(peripheral). scanner and broadcaster does not establish BLE connection actually.
Regarding to the write failure, it was reject at the function gatts_write_attr_perm_check when application try to write data to database. the code just like below:
else if (!(perm & GATT_WRITE_ALLOWED))
{
status = GATT_WRITE_NOT_PERMIT;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check -GATT_WRITE_NOT_PERMIT");
}
So, the problem is the recorded perm was not eligible with GATT_WRITE_ALLOWED, which is
> (GATT_PERM_WRITE | GATT_PERM_WRITE_ENCRYPTED |\
> GATT_PERM_WRITE_ENC_MITM | GATT_PERM_WRITE_SIGNED |\
> GATT_PERM_WRITE_SIGNED_MITM)
So, could you have a following try:
1) unpair the device and pair the device again.
2) enable the high security level e.g. enable the MITM.
And I assume you want to enable the notification right? I could not get all the code you have but can you also try this(quote from Android website):
private BluetoothGatt mBluetoothGatt;
BluetoothGattCharacteristic characteristic;
boolean enabled;
...
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
...
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);

Will this permission cause an error? (The answer doesn't work?)

After doing tons of research on the topic, I learned that my app may not show up for tablets in the Play Store if I have some permissions that the tablet cannot handle. Here are my current permissions:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIBRATE" android:permission ="false" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.INTERNET" />
Will any of these permissions cause the app to not show up in the play store?
Some tablets may not be able to handle the <uses-permission android:name="android.permission.READ_PHONE_STATE" /> because don't get calls...So, I need to do something in my java code saying:
if(Device has the ability to get calls){ //Execute code}
So, since the telephone thing is optional, I changed it's permission to:
<uses-feature android:name="android.permission.READ_PHONE_STATE" android:required="false"/>
How do I get that? If you need it, this is where I am actually checking if the user is getting a call, I use it to mute my application:
private PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
onPhoneCallInterrupt(); //Method I created that just mutes the audio
} else if (state == TelephonyManager.CALL_STATE_IDLE) {
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
onPhoneCallInterrupt(); //Method I created that just mutes the audio
}
}
};
So, what do I do to handle the exception that may occur if a tablet is using the app, like this?
if(Device has the ability to get calls){ //Execute code}
Thanks,
Ruchir
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); //gets the current TelephonyManager
if (tm.getSimState() != TelephonyManager.SIM_STATE_ABSENT){
//the device has a sim card
} else {
//no sim card available
}
Check more here
Keep your phone state permission on an if-else block. When user will try to access that feature or you might need to check phone state, throw a dialog box on the screen. This link shows how to ask for user's permission.
From API 23, User's will need to explicitly permit each and every permission so, it is a good thing if you do that for all.
Beside, upon users permission, the manifest file will be overwritten so, you won't have to worry about that either.
Does it solve ur issue?

Vibrator permission force close

I have this line of code calling 2 seconds from the vibrator_service;
Vibrator v = (Vibrator)
getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(2000);
and this in my manifest
<permission
android:name="android.permission.VIBRATE" ></permission>
But I am still getting a force close java.lang.security.exception: Requires Vibrate Permission. Have I declared the permission wrong??
You need to add a uses-permission tag in the manifest file (as a child of the manifest element, same as the permission tag):
<uses-permission android:name="android.permission.VIBRATE" />
As far as I know, the permission tag is only used to add additional text/graphic information to the permissions request when downloading the app, or to add new permissions to provide additional information to your users. I usually use both to be safe.

Categories