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;
}
Related
Currently working with the Brother SDK for a label Printer and when I call Asset Manager, the Bitmap appears but when it is parsed to print image it crashes.
if (myPrinter.startCommunication()) {
AssetManager assetManager = getAssets();
Bitmap bitmap = null;
try{
bitmap = BitmapFactory.decodeStream(new BufferedInputStream(assetManager.open("meme.bmp")));
}catch(Exception e){
e.printStackTrace();
}
PrinterStatus result = myPrinter.printImage(bitmap);
if (result.errorCode != ErrorCode.ERROR_NONE) {
Log.d("TAG", "ERROR - " + result.errorCode);
}
myPrinter.endCommunication();
}
Stack Readout
Debugger printout, with Image Preview.
For anyone got stuck even if they made sure they have the write permission granted, it was about the working path b-PAC trying to create.
The default path is: /storage/emulated/0/com.brother.ptouch.sdk/template
Just define your own path in PrinterInfo object. Set the workPath variable as such:
PrinterInfo mPrintSettings = mPrinter.getPrinterInfo();
mPrintSettings.workPath = "your/custom/work/path";
It says in the document that you don't even need the permission if you do so. But I'm going to keep it anyway.
I had this issue as well. Have you made sure that the android.permission.WRITE_EXTERNAL_STORAGE permisson is granted.
Having this in the manifest file wasn't enough, but by requesting permisson from the user, this specific error went away.
Credit to this post on SO
I am currently trying to reduce the quality of videos and audio before uploading to and online cloud database. Below is the code I have been using to record videos.
recordVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
Changing the 0 to 1 in EXTRA_VIDEO_QUALITY will increase the quality and vice versa, but the file is still too large to download if it a 30 second or more video.
private void RecordVideoMode() {
Intent recordVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (recordVideoIntent.resolveActivity(getPackageManager()) != null) {
videoFile = createVideoFile();
// Continue only if the File was successfully created
if (videoFile != null) {
videoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
videoFile);
recordVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
recordVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoURI);
startActivityForResult(recordVideoIntent, REQUEST_VIDEO_CAPTURE);
}
}
}
Any help is very much appreciated!
You can go with this two methods :
Encode it to a lower bit rate and/or lower resolution. Have a look here:
Is it possible to compress video on Android?
Try to zip/compress it. Have a look here:
http://www.jondev.net/articles/Zipping_Files_with_Android_%28Programmatically%29
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
I've been following a tutorial where I'm trying to use the JavaOSC library to add functionality for a native Android app to send OSC messages.
Below is the code I have for setting up an OSC thread:
private String myIP = "192.168.0.3";
private int myPort = 1234;
private OSCPortOut oscPortOut;
// This thread will contain all the code that pertains to OSC
private Thread oscThread = new Thread() {
#Override
public void run() {
try {
// Connect to some IP address and port
oscPortOut = new OSCPortOut(InetAddress.getByName(myIP), myPort);
Log.v(TAG, "CREATED PORT");
} catch(UnknownHostException e) {
Log.v(TAG, "error is", e);
// Error handling when your IP isn't found
return;
} catch(Exception e) {
// Error handling for any other errors
Log.v(TAG, "error is", e);
return;
}
/* The second part of the run() method loops infinitely and sends messages every 500
* milliseconds.
*/
while (true) {
if (oscPortOut != null) {
// Creating the message
Log.v(TAG, "CREATED MESSAGE");
Object[] thingsToSend = new Object[3];
thingsToSend[0] = "Hello World";
thingsToSend[1] = 12345;
thingsToSend[2] = 1.2345;
/* The version of JavaOSC from the Maven Repository is slightly different from the one
* from the download link on the main website at the time of writing this tutorial.
*
* The Maven Repository version (used here), takes a Collection, which is why we need
* Arrays.asList(thingsToSend).
*
* If you're using the downloadable version for some reason, you should switch the
* commented and uncommented lines for message below
*/
OSCMessage message = new OSCMessage(myIP, Arrays.asList(thingsToSend));
// OSCMessage message = new OSCMessage(myIP, thingsToSend);
/* NOTE: Since this version of JavaOSC uses Collections, we can actually use ArrayLists,
* or any other class that implements the Collection interface. The following code is
* valid for this version.
*
* The benefit of using an ArrayList is that you don't have to know how much information
* you are sending ahead of time. You can add things to the end of an ArrayList, but not
* to an Array.
*
* If you want to use this code with the downloadable version, you should switch the
* commented and uncommented lines for message2
*/
ArrayList<Object> moreThingsToSend = new ArrayList<Object>();
moreThingsToSend.add("Hello World2");
moreThingsToSend.add(123456);
moreThingsToSend.add(12.345);
OSCMessage message2 = new OSCMessage(myIP, moreThingsToSend);
//OSCMessage message2 = new OSCMessage(myIP, moreThingsToSend.toArray());
try {
// Send the messages
oscPortOut.send(message);
oscPortOut.send(message2);
Log.v(TAG, "SENDING");
// Pause for half a second
sleep(500);
} catch (Exception e) {
// Error handling for some error
}
}
}
}
};
I ended up getting some network errors, where research showed that I may need to add the following permission lines to the Android.manifest file:
<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" />
However, after adding those lines and running the app on the Simulator (a Nexus 7), but I keep getting errors saying that "The app has stopped".
This is actually my first Android project, so I'm sure I may be missing something obvious here (such as where to find logs in the case of this crash).
EDIT:
I'm on API 27. The only log I see from LogCat is the following:
12-13 17:07:54.299 2981-3026/com.deviantdev.pdsampleproject D/EGL_emulation: eglMakeCurrent: 0xa9f842a0: ver 2 0 (tinfo 0xa9f83300)
12-13 17:07:55.344 2981-2981/com.deviantdev.pdsampleproject I/Choreographer: Skipped 103 frames! The application may be doing too much work on its main thread.
12-13 17:07:55.362 2981-3026/com.deviantdev.pdsampleproject D/EGL_emulation: eglMakeCurrent: 0xa9f842a0: ver 2 0 (tinfo 0xa9f83300)
[ 12-13 17:07:55.416 2981: 2981 D/ ]
PlayerBase::stop() from IPlayer
12-13 17:07:55.416 2981-2981/com.deviantdev.pdsampleproject D/AudioTrack: stop() called with 90720 frames delivered
12-13 17:07:55.432 2981-2981/com.deviantdev.pdsampleproject I/opensl_stream: Input buffer size estimate: 0
12-13 17:07:55.432 2981-2981/com.deviantdev.pdsampleproject I/opensl_stream: Output buffer size estimate: 0
12-13 17:07:55.432 2981-2981/com.deviantdev.pdsampleproject I/opensl_stream: Lowest margin: 11968
From Android Marshmallow(API 23) and above , you may need to implement Runtime Permission . Here is an example ,
if (Build.VERSION.SDK_INT >= 23) {
String[] PERMISSIONS = {android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(mContext, PERMISSIONS)) {
ActivityCompat.requestPermissions((MainActivity) mContext, PERMISSIONS, REQUEST );
} else {
//do something
}
} else {
//do something
}
You can write this code inside onCreate and this is example to get WRITE_EXTERNAL_STORAGE permission at run time .
I think you should modify this line
String[] PERMISSIONS = {android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
to
String[] PERMISSIONS = {android.Manifest.permission.INTERNET,android.Manifest.permission.ACCESS_NETWORK_STATE,android.Manifest.permission.ACCESS_WIFI_STATE};
Hope it's helpful .
I've checked the other answers and they didn't help me with this error. Maybe I'm doing something else wrong.
Here's my code:
void uploadPic() throws FileNotFoundException
{
FileInputStream fis = new FileInputStream(path);
FTPClient con = new FTPClient();
int bytesAvailable;
try
{
con.connect("ftp://ftp.drivehq.com/");
Toast.makeText(this, "Connected to FTP", Toast.LENGTH_SHORT).show();
if (con.login("x", "x"))
{
Toast.makeText(this, "Logged in", Toast.LENGTH_SHORT).show();
con.enterLocalPassiveMode(); // Active mode doesn't really work on Android
bytesAvailable = fis.available();
byte[] barray = new byte[bytesAvailable];
fis.read(barray);
ByteArrayInputStream in = new ByteArrayInputStream(barray);
boolean result = con.storeFile("/CameraUpload.jpg", in);
in.close();
if (result) Log.v("Upload Result", "Succeeded");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
I've added INTERNET permission to my project.
The logcat shows these errors:
android.os.NetworkOnMainThreadException
W/System.err(17531): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
W/System.err(17531): at java.net.InetAddress.lookupHostByName(InetAddress.java:391
I'm connected to the internet via Wifi.
That exception seems to be thrown when you try to perform network operations (such as FTP) from your main thread. This is not allowed for performance reasons (so that the application doesn't appear to lock up to the user, when performing an action which may take a while). Assuming you are using Honeycomb or higher, you would need to move the code that makes the connection into its own child thread.
http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
http://developer.android.com/guide/practices/design/responsiveness.html
Most likely, this error means that your device cannot resolve ftp.drivehq.com to its IP address. I can't say for sure because you only pasted part of the error log. Make sure you have network connection and that your DNS is working correctly. See if you can connect to this same site via android browser, for example.