How to solved permission denied when download file in android - android

i have create a modul to download file from server to my android apps like this
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection connection = url.openConnection();
connection.connect();
// getting file length
int lengthOfFile = connection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
String timestamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
//Extract file name from URL
fileName = f_url[0].substring(f_url[0].lastIndexOf('/') + 1, f_url[0].length());
//Append timestamp to file name
fileName = timestamp + "_" + fileName;
//External directory path to save file
folder = Environment.getExternalStorageDirectory() + File.separator + "simpel/";
//Create androiddeft folder if it does not exist
File directory = new File(folder);
if (!directory.exists()) {
directory.mkdirs();
}
// Output stream to write file
OutputStream output = new FileOutputStream(folder + fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lengthOfFile));
Log.d(TAG, "Progress: " + (int) ((total * 100) / lengthOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
return "Downloaded at: " + folder + fileName;
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return "Something went wrong";
}
but when i try to download, i always get error like this
E/Error::
/storage/emulated/0/simpel/2019.07.06.18.57.51_REGISTER_TILANG.xlsx
(Permission denied)
even though I have added this to my manifest
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
i use this libary:
implementation 'pub.devrel:easypermissions:0.2.0'

I know it's been more than a year but I hope this helps someone.
I worked with your code now and I found out the mistake you might have made.
You might have added these android.permission.READ_EXTERNAL_STORAGE android.permission.WRITE_EXTERNAL_STORAGE to your manifest.xml but you need to ask for the permission in your code.
Even using the library (same I used) implementation 'pub.devrel:easypermissions:0.2.0' it seems you didn't check for both READ and WRITE permissions (something like this):
private static final int WRITE_REQUEST_CODE = 1;
if (EasyPermissions.hasPermissions(DownloadActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//your asyncTask to download
downloadFile.execute(url);
} else {
//If permission has no be granted, request
EasyPermissions.requestPermissions(DownloadActivity.this, "This app needs access to your file storage" , WRITE_REQUEST_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
}
Notice that in the code above, only WRITE permission was checked. If there isn't, then READ permission was requested (which is kind of contradictory). The correct would be checking for both permissions then if either of them has not been granted, the system will request for thr two. Compare the following code:
private static final int REQUEST_CODE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
if (EasyPermissions.hasPermissions(DownloadActivity.this, PERMISSIONS_STORAGE)) {
//your asyncTask to download
downloadFile.execute(url);
} else {
//If permission has not been granted, request
EasyPermissions.requestPermissions(DownloadActivity.this, "This app needs access to your file storage", REQUEST_CODE, PERMISSIONS_STORAGE);
}
I had similarcode as yours and had the same error, I fixed it this way.

Related

How to download the file with original extension from Firebase storage?

I'm trying to download files from Firebase storage. But when I download it, it's giving some files with .bin extension. But I want to get the original file name.
Here is my code.
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
InputStream input = new BufferedInputStream(url.openStream(),
8192);
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+"/Download/"+ URLUtil.guessFileName(f_url[0], null, null));
Log.i("File name",URLUtil.guessFileName(f_url[0], null, null));
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
In there f_url is the firebase download url. Thank you.
The built in way of doing this is actually quite straightforward:
StorageReference reference = storage.getReferenceFromUrl("https://firebasestorage.googleapis.com/...");
// Assuming that the file is "name.extension" in Storage
String name = reference.getName().split(".")[0]
String extension = reference.getName().split(".")[1]
File localFile = File.createTempFile(name, extension);
reference.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
// Local temp file has been created
}
});
But if you don't want to do it the easy way...
Let's take a brief look at how you're naming your file: URLUtil.guessFileName(f_url[0], null, null)
According to the URLUtil.guessFileName() docs: "Guesses canonical filename that a download would have, using the URL and contentDisposition. File extension, if not defined, is added based on the mimetype."
I'm assuming that your f_url[0] is a file with no extension, and since you provide no contentDisposition or mimetype as arguments to guessFileName, there's no way it can possibly know what file extension you want.
You can get the contentDisposition and contentType (same as mimetype) from Storage Metadata, and if you name your file in Storage with an extension, you should be good to go.

add checking update function in android app

I want to add checking update function in android app
I know this question is asked already and post a lib on Github
How to allow users to check for the latest app version from inside the app?
but my cant i post on the Google Play Store due to some problem of copyright
So i cant use the method
what should i do?
Your code to check update once in a day. only works when you open app once in a day. in onCreate() of your launcher activity.
SharedPreferences mSettings = PreferenceManager.getDefaultSharedPreferences
(Dashboard.this);
long lastUpdateTime = mSettings.getLong("lastUpdateTime", 0);
/* Should Activity Check for Updates Now? */
if ((lastUpdateTime + (24 * 60 * 60 * 1000)) < System.currentTimeMillis()) {
/* Save current timestamp for next Check*/
SharedPreferences.Editor editor = mSettings.edit();
lastUpdateTime = System.currentTimeMillis();
editor.putLong("lastUpdateTime", lastUpdateTime);
editor.commit();
/* Start Update by using asynctask that run in backGround eg. http://portal.aksuniversity.com:8089/utility/apkversion*/
String URL = "your app url in my case ;
AsyncRequest asyncRequestTime = new AsyncRequest(Dashboard.this, "GET", null,
null, 3);
asyncRequestTime.execute(URL);
}
the response you will get is json object. get jsonObject key of version code and match it with your app version code
int versionCode = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0).versionCode;
if (versionCode < jsonObject.getString(""VersionCode))
//if greater show dialog for app update and download apk with new url of your app which will give you apk
for download you can use
private String callApiDownload(String address) {
try {
URL url = new URL(address);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
if (Cookie.getCookie() != null)
urlConnection.addRequestProperty("Cookie", Cookie.getCookie());
if (urlConnection.getResponseCode() == 200) {
File file = new File(Environment.getExternalStorageDirectory() + "/" + folderName);
boolean fileExist = true;
if (!file.exists()) {
fileExist = file.mkdir();
}
if (fileExist) {
String FileName = Environment.getExternalStorageDirectory() + "/" + folderName + "/"
+ fileName;
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(FileName);
int bytesRead;
byte[] buffer = new byte[4096];
int total = 0;
int contentLength = urlConnection.getContentLength();
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
publishProgress((int) ((total * 100) / contentLength));
}
}
outputStream.flush();
outputStream.close();
inputStream.close();
return fileName;
}
} else {
InputStream inputStream = new BufferedInputStream(urlConnection.getErrorStream());
return fileName = Connection.convertInputStreamToString(inputStream);
}
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return fileName;
}
on download complete you can use intent to open apk for installation which will prompmt user for new update apk installation.
The first code will call the api once a day when user open the app. This api will return the json object of your app version code and version name. You need to manually maintain it when you create new apk for user. Parse the json object. And get the version code. In your app check if api version code is greater than your app version code. And if it is than fire a new api which is the last code i have given that download the your apk from url(in server you have to place apk for specified urlby calling which your apk will downloaded) which is last code you need to run in backthread asynctak. I will create the source code more proper and notifie you.

get sd card path in android vs hard coded path

my code works fine, it downloads image to sd card, however , i get this warning where i defined my sd card path "Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead"
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream("/sdcard/.temp");//.temp is the image file name
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
}
return null;
}
protected void onProgressUpdate(String... progress) {
Log.d("ANDRO_ASYNC", progress[0]);
}
the problem is, if i use the suggested solution, then i won't be able to give my downloaded file a new name (".temp")
When working with files and directories, it's better to work with File objects rather than with strings. Here's how you can address the warning:
File dir = Environment.getExternalStorageDirectory();
File tmpFile = new File(dir, ".temp");
OutputStream output = new FileOutputStream(tmpFile);
That creates a File object that points to a file named ".temp" in the environment's external storage directory. It then opens it for writing using a different constructor of the FileOutputStream class.
If you need the file path as a string instead (say, for printing), you can do that too:
String tmpFileString = tmpFile.getPath();
Or if you decide to use the java.nio API in the future and need a Path object:
Path tmpFilePath = tmpFile.toPath();

Unable to load image in a ImageView from the Internal Storage

I am trying to add the Image from the the Internal Memory.
I am trying to use this code for that
ImageView message_image=(ImageView)v.findViewById(R.id.message_image);
File imgFile = new File(img_db);
Log.e("img_db",img_db+"------------->");
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
message_image.setImageBitmap(myBitmap);
}
here img_db is my path that i am getting from my Sqlite table.when i log it i get the fath like this
E/img_db: file:///storage/sdcard0/download/img11024FILE.jpg------------->
I have already given this permission in my manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
For downloading image and save to the phone i am using this code
public String downloadFile(String url_i_) {
try {
URL url
= new URL(url_i_);
Log.e("url_fetch--->img", String.valueOf(url));
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
// connect
urlConnection.connect();
// set the path where we want to save the file
SDCardRoot = Environment.getExternalStorageDirectory();
// create a new file, to save the downloaded file
rand = new External_function().getnRandom();
file = new File(SDCardRoot, "/download/img" + rand+".jpg");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
// this is the total size of the file which we are downloading
totalSize = urlConnection.getContentLength();
// create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
// update the progressbar //
float per = ((float) downloadedSize / totalSize) * 100;
/*cur_val.setText("Downloading.... " + downloadedSize
+ "KB / " + totalSize + "KB (" + (int) per
+ "%)");*/
String i = "Downloading.... " + downloadedSize
+ "KB / " + totalSize + "KB (" + (int) per
+ "%)";
}
fileOutput.close();
file = new File(Environment.getExternalStorageDirectory() + "/download/img" + rand+".jpg"); // set your audio path
file_path= String.valueOf(Uri.fromFile(file));
} catch (final Exception e) {
Log.e("////////////////file", String.valueOf(e));
}
return file_path;
}
And inside my service class when i get the image path in return then i store it inside my sqlite table like this
String img = socketOperator.downloadFile(event_img);
localstoragehandler.insert(id, msg_user_by, msg_read_by, msg_content, msg_grp_id, ms‌​g_sent_time,type,event_time,event_lat,event_log,event_name,event_address,img);
I checked the path with image and id are same.I try this but really don't know what I am doing wrong.
You need this permission:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
READ_EXTERNAL_STORAGE not WRITE_EXTERNAL_STORAGE
#CommonsWare has already answered this. Try changing how you get your path. (Original Answer)
Why would this happen?
Because the path to external storage has changed over the years, which is why you should have never hard-coded the path in the first place.
how can I get the path directory in a more "formal and right" way
instead of hardcoding the path?
Use Environment.getExternalStorageDirectory().
On your test environment, /sdcard is a symlink or hardlink to /storage/sdcard0, as set up by the device manufacturer. However, there is no guarantee that all devices will have such an /sdcard symlink.
If that does not help you. This definitely will: Reading from internal storage.
UPDATE
Please look for all usages of this "/download/img" ...
You are missing a "/" ... Replace it with "/download/img/"

changing byte when copy file not working

changing byte when copy file form one location to another not working whats wrong in my code please help me if i remove string s1; then its work perfect just duplicate original file when i alter bytes using s1 string its not work
samplet.text file contain numbers
3434214280
3044559080
3154356865
3312430124
3334491537
package com.example.copyfilefromdirectorytoanother;
ublic class MainActivity extends Activity {
private static final String TAG = "MainActivity.java";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// your sd card
String sdCard = Environment.getExternalStorageDirectory().toString();
// the file to be moved or copied
File sourceLocation = new File (sdCard + "/sample.txt");
// make sure your target location folder exists!
File targetLocation = new File (sdCard + "/MyNewFolder/sample.txt");
// just to take note of the location sources
Log.v(TAG, "sourceLocation: " + sourceLocation);
Log.v(TAG, "targetLocation: " + targetLocation);
try {
// 1 = move the file, 2 = copy the file
int actionChoice = 2;
// moving the file to another directory
if(actionChoice==1){
if(sourceLocation.renameTo(targetLocation)){
Log.v(TAG, "Move file successful.");
}else{
Log.v(TAG, "Move file failed.");
}
}
// we will copy the file
else{
// make sure the target file exists
if(sourceLocation.exists()){
InputStream in = new
FileInputStream(sourceLocation);
OutputStream out = new
FileOutputStream(targetLocation);
// Copy the bits from instream to outstream
String s1;
// byte[] theByteArray ;
byte[] buf = new byte[1024];
byte[] theByteArray = new byte[1024];
int len;
int n =1;
while ((len = in.read(buf)) > 0) {
s1= "BEGIN:VCARD \n VERSION:2.1 \n N:;UNKNOWN "+n+";;; \n FN:UNKNOWN "+n+"
\n TEL;CELL;PREF:+92"+buf+" \n END:VCARD ";
theByteArray=s1.getBytes();
out.write(theByteArray, 0, len);
n=n+1;
}
in.close();
out.close();
Log.v(TAG, "Copy file successful.");
}else{
Log.v(TAG, "Copy file failed. Source file
missing.");
}
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Well, you're reading in len bytes, appending data to it, then writing out len bytes. That's wrong, you need to do out.write(theByteArray, 0, theByteArray.length); I can see other possible problems there too, but your file may be small enough to avoid them.

Categories

Resources