This question already has answers here:
Unable to save image file in android oreo update. How to do it?
(2 answers)
Closed 4 years ago.
I'm saving image from glide to device. I'm asking for permission in first App run cause that's what my app do.
final File myDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DesiJewellery/");
public void saveImage(Bitmap bitmap, String img_title) {
fname = img_title;
myDir.mkdirs();
File image = new File(myDir, fname);
FileOutputStream outStream;
if (image.exists()) {
image.delete();
}
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outStream);
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (success) {
Toast.makeText(getActivity(), "Design saved - " + img_title, Toast.LENGTH_SHORT).show();
} else {
// Toast.makeText(getActivity(), "Something went wrong.", Toast.LENGTH_LONG).show();
}
// this one to show in gallery:
}
It's working fine in emulator, but in real device it shows
java.io.FileNotFoundException: /storage/emulated/0/DesiJewellery/m_aad14.jpg (Permission denied)
Permission Check. I run it on MainActivity.
public void isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED && checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
} else {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
} else {
}
}
P.S.- I have 2 Real devices. It's working in Mashmallow and Nougat Emulator but Problem is in Only Oreo.
You can try the following:
AsyncTask fileTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + "MyApplication");
if (!directory.exists()) {
directory.mkdirs();
}
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String name = " "+n+".jpg";
File pictureFile = new File(directory, name);
pictureFile.createNewFile();
try {
FileOutputStream out = new FileOutputStream(pictureFile);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
fileTask.execute();
Refer this for help
You should add WRITE_EXTERNAL_PERMISSION in Android Mainifest like below :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:node="replace"/>
Related
val filePath = getString(R.string.file_path)
val file = File(filePath)
var lines: List<String?> = ArrayList()
if(!file.exists()) {
try {
if (Environment.getExternalStorageState()==Environment.MEDIA_MOUNTED) {
file.createNewFile()
}
} catch (e: IOException) {
AlertDialog.Builder(this)
.setTitle(getString(R.string.No_records_file))
.setMessage(getString(R.string.cant_create_file))
.setNeutralButton(
R.string.Exit
) { dialog, id -> finish() }.show()
}
}
It works on Android 8.0.0, 9.0 . I am not sure about android, but this problem appeared on Mi9T pro
With Android Q, you can no longer directly access to the file system. Use the SAF (Storage Access Framework) instead.
First add this rules;
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Ask permissions from activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//ASK HERE...
if (shouldAskPermissions()) {
askPermissions();
}
}
-
//// ASK METHODS
protected boolean shouldAskPermissions() {
return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}
protected void askPermissions() {
String[] permissions = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE"
};
int requestCode = 200;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, requestCode);
}
}
then for create file use this code;
File directory = new File(Environment.getExternalStorageDirectory()+java.io.File.separator +"AppName");
try{
if(!directory.exists()) {
System.out.println("Directory created");
directory.mkdirs();
} else {
System.out.println("Directory is not created");
}
File f = new File(directory.getPath()+"/"+ "ENTER_FILE_NAME" + ".jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
System.out.println("FILE PATH:" + f.getPath());
}catch(Exception e){
e.printStackTrace();
}
on Android API 29, getExternalStorageDirectory is deprecated, you should use getExternalFilesDir instead.
I'm working on an app where I'm downloading a PDF file, saving it to internal storage and then opening that file in other app using FileProvider.
Note: It may be a duplicate question, I've gone through most of the questions on StackOverflow, but still didn't find the solution.
The file is getting downloaded fine but when I'm opening it, it is empty.
The downlaoded file is 30 kb and it has 5 pages but all are empty.
Initially, I thought it is empty because the other app doesn't have permission to open the file, but I did another thing to check whether it is a permission issue. I've saved the file to external storage, still, it was empty. So, it means it is not a permission issue.
Please Note:
Along with pdf file, there is some .xls file as well and when I'm opening those in excel android app, it says cannot open the file. This indicates, that there is some issue while writing the byte stream.
Retrofit Interface.java
#GET(ApiConstants.END_POINT_DOWNLOAD_DOCUMENT)
#Streaming
Call<ResponseBody> downloadDocument(#Query("bucket") String bucket, #Query("filename") String fileName);
Code to Download the file: Here I'm checking if a file is already there, then return the file, otherwise download the file.
public LiveData<Resource<File>> openOrDownloadFile(String bucket, String fileName) {
MutableLiveData<Resource<File>> documentLiveData = new MutableLiveData<>();
documentLiveData.postValue(Resource.loading(null));
Context context = MyApp.getInstance();
final File file = new File(context.getFilesDir(), fileName);
if (file.exists()) {
documentLiveData.postValue(Resource.success(file));
} else {
Call<ResponseBody> call = apiService.downloadDocument(bucket, fileName);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
appExecutors.diskIO().execute(new Runnable() {
#Override
public void run() {
try {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
inputStream = response.body().byteStream();
outputStream = new FileOutputStream(file);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
}
documentLiveData.postValue(Resource.success(file));
outputStream.flush();
} catch (IOException e) {
documentLiveData.postValue(Resource.error("Error: Unable to save file/n"+e.getLocalizedMessage(), null));
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
Log.e(AppConstants.TAG, e.getMessage(), e);
documentLiveData.postValue(Resource.error("Error: Unable to save file/n"+e.getLocalizedMessage(), null));
}
}
});
} else {
documentLiveData.postValue(Resource.error("Unable to download file", null));
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
documentLiveData.postValue(Resource.error(t.getLocalizedMessage(), null));
}
});
}
return documentLiveData;
}
Fragment Code
private void onItemClickListener(Document document) {
mDocumentsViewModel.openORDownloadFile(document.getType(), document.getName()).observe(this, new Observer<Resource<File>>() {
#Override
public void onChanged(#Nullable Resource<File> fileResource) {
binding.setResource(fileResource);
if (fileResource.status == Status.SUCCESS) {
openFile(fileResource.data);
}
}
});
}
void openFile(File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID, file);
intent.setDataAndType(uri, mDocumentsViewModel.getMimeType(file.getAbsolutePath()));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
PackageManager pm = getActivity().getPackageManager();
if (intent.resolveActivity(pm) != null) {
startActivity(intent);
} else {
Toast.makeText(getActivity(), "This file cannot be opened on this device. Please download some compatible app from play store", Toast.LENGTH_SHORT).show();
}
}
Following are the versions :
ext.retrofit_version = "2.4.0"
ext.okhttp_version = "3.8.0"
I'm struggling with this issue, it'll be a great help if you can point out the issue. Thank you.
Update: The problem was with the backend APIs. My code was correct. Once they've fixed the problem at there side, it started working at my side without any changes.
This question already has answers here:
Android: install .apk programmatically [duplicate]
(4 answers)
Closed 5 years ago.
I've seen a few answers related to this but can't quite seem to find what I'm looking for. Say I have a self hosted app. Now say I've made some changes to that app and would like to let the user know within the app that there is an update available. I can get the app to successfully download the apk file and begin installing it. After the installation is "finished" the app closes out. When I restart the app none of the changes I've made have been applied. So it appears the installation has failed, but there was no apparent crash. However, when I install the apk that was downloaded from the Downloads manager it installs just fine and the changes I have made are applied. Any ideas? Here is the section of code I use to download and install programmatically:
String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
String fileName = "TheApp.apk";
destination += fileName;
final Uri uri = Uri.parse("file://" + destination);
String url = "myapplocation";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Downloading necessary update files.");
request.setTitle("Updating The App");
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setDataAndType(uri,
manager.getMimeTypeForDownloadedFile(downloadId));
startActivityForResult(install, 0);
unregisterReceiver(this);
}
};
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
Get VersionName and VersionCode for current Running application.
code:
try {
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
Common.VersionName = pInfo.versionName;
Common.VersionCode = pInfo.versionCode;
Log.e("VersionCode", ">>>>>>>>>>" + Common.VersionCode + Common.VersionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
**Check the Version Names**
if (!Common.VersionName.equals(Common.VersionNamefromWebApi)) {
AlertDialogUpdate(MakeTransactionActivity.this, Common.AppUpdateTitle, "YokoYepi Version" + Common.VersionNamefromWebApi + " available.");
}
**Alert Dialog Box**
public void AlertDialogUpdate(Activity activity, String title, CharSequence message) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setCancelable(false);
if (title != null) builder.setTitle(title);
builder.setMessage(message);
builder.setPositiveButton("UPDATE", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
new DownloadNewVersion().execute();
dialog.dismiss();
}
});
builder.show();
}
**Download and Install the .apk file from URL**
class DownloadNewVersion extends AsyncTask<String, Integer, Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
bar = new ProgressDialog(MakeTransactionActivity.this);
bar.setCancelable(false);
bar.setMessage("Downloading...");
bar.setIndeterminate(true);
bar.setCanceledOnTouchOutside(false);
bar.show();
stoptimertask();
}
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
bar.setIndeterminate(false);
bar.setMax(100);
bar.setProgress(progress[0]);
String msg = "";
if (progress[0] > 99) {
msg = "Finishing... ";
} else {
msg = "Downloading... " + progress[0] + "%";
}
bar.setMessage(msg);
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
startTimer();
bar.dismiss();
if (result) {
Toast.makeText(getApplicationContext(), "Update Done",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Error: Try Again",
Toast.LENGTH_SHORT).show();
}
}
#Override
protected Boolean doInBackground(String... arg0) {
Boolean flag = false;
try {
String PATH;
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if (isSDPresent) {
PATH = Environment.getExternalStorageDirectory() + "/Download/";
} else {
PATH = Environment.getDataDirectory() + "/Download/";
}
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file, "yokoyepi.apk");
if (outputFile.exists()) {
outputFile.delete();
}
// Download File from url
URL u = new URL(Common.AppUpdateURL);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
// Install dowloaded Apk file from Devive----------------
OpenNewVersion(PATH);
flag = true;
} catch (MalformedURLException e) {
Log.e(TAG, "Update Error: " + e.getMessage());
flag = false;
} catch (IOException e) {
Log.e(TAG, "Update Error: " + e.getMessage());
flag = false;
} catch (Exception e) {
Log.e(TAG, "Update Error: " + e.getMessage());
flag = false;
}
return flag;
}
}
void OpenNewVersion(String location) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(location + "yokoyepi.apk")),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
// if your not install u should call the function in onResume().
// again it will check whether apk updated or not.
My android app on Android-M have the permission declared in Manifest.
android.permission.WRITE_EXTERNAL_STORAGE
My app starts media player which sends control to Jni layer and then to MediaPlayerService and finally to NuPlayer. I understand that my app and NuPlayer are running in two seperate process (http://rxwen.blogspot.in/2010/01/understanding-android-media-framework.html).
Now if i try to create a file in sdcard from native process, suppose from (NuPlayer.cpp) :
FILE *file = fopen("/storage/emulated/0/Test/test.txt", "w+");
file is coming as null and errno is 13 (No permission). So need to know how to give permission to native process to create file on sdcard on Android M.
Thanks in advance for the help.
In Marshmallow you need to ask for permission to user to achieve this try,
1.in your manifest add,
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
2.Create function for write into external storage.
private void createFileExternalStorage() {
MarshMallowPermission marshMallowPermission = new MarshMallowPermission(this);
if (!marshMallowPermission.checkPermissionForExternalStorage())
marshMallowPermission.requestPermissionForExternalStorage();
File backupFile;
File appFolder;
// if SDCard available
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
appFolder = new File(Environment.getExternalStorageDirectory(), getResources().getString(R.string.app_name));
if (!appFolder.exists())
appFolder.mkdir();
Log.d(TAG,"In External");
}else { // if not SDCard available
ContextWrapper cw = new ContextWrapper(this);
appFolder = cw.getDir(getResources().getString(R.string.app_name), Context.MODE_PRIVATE);
if (!appFolder.exists())
appFolder.mkdir();
Log.d(TAG,"In internal");
}
//create a new file, to save the downloaded file
backupFile = new File(appFolder, "backup.txt");
Log.d(TAG, "file #" + backupFile.getAbsolutePath());
try {
FileOutputStream f = new FileOutputStream(backupFile);
PrintWriter pw = new PrintWriter(f);
pw.println("Hi , How are you");
pw.println("Hello");
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "******* File not found. Did you" +
" add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
} catch (IOException e) {
e.printStackTrace();
}
}
3.Create class MarshMallowPermission to get & ask for permission.
public class MarshMallowPermission {
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
Activity activity;
public MarshMallowPermission(Activity activity) {
this.activity = activity;
}
public boolean checkPermissionForExternalStorage(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public void requestPermissionForExternalStorage(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(activity, "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
}
}
}
I continually get an error.
Each time that I run the code in the emulator, it shows the 'Toast' that the directory was created, but there must be an error shortly after that line of code. The error that comes up is:
"/storage/sdcard/Pictures/screenshot.png: open failed: ENOENT (No such file or directory)"
I have place the relevant code below.
<manifest
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19"
/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"
/>
</manifest>
public class myActivity {
private void openScreenPrint() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)){
View v1 = findViewById(R.id.myRelativeLayout).getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap myBM = Bitmap.createBitmap(v1.getDrawingCache());
saveBitmap(myBM);
v1.setDrawingCacheEnabled(false);
}
else{
Toast.makeText(this, "No Permission to Write", Toast.LENGTH_SHORT).show();
}
}
public void saveBitmap(Bitmap bitmap) {
FileOutputStream fos = null;
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File dir = new File(filePath);
if (!dir.exists()){
dir.mkdirs();
Toast.makeText(this, "created", Toast.LENGTH_LONG).show(); //This line shown every time
}
String fileName = "screenshot" + ".png";
File imagePath = new File(filePath, fileName);
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
//Log.e("Err", e.getMessage(), e);
} catch (IOException e) {
//Log.e("Err", e.getMessage(), e);
}
}
}
Have you created an SD Card in your AVD? If not, here's the entry that you'll want to use when creating/editing your simulated device:
You do not actually know that the directory is actually being created. You are making the Toast whether the directory create succeeds or not. You should change this section:
if (!dir.exists()){
dir.mkdirs();
Toast.makeText(this, "created", Toast.LENGTH_LONG).show();
}
to test if the directory was actually created successfully. File.mkdirs() returns a boolean.
if (!dir.exists()) {
Toast.makeText(this, "dir not exists. attempting to create...", Toast.LENGTH_SHORT).show();
if (dir.mkdirs()) {
Toast.makeText(this, "dir created", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "dir creation failed", Toast.LENGTH_SHORT).show();
}
}