how to copy directory (folder) to usb storage - android

i am trying to copy whole directory to usb storage :
File Sdfile = new File(Environment.getExternalStorageDirectory(), "myfolder");
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.setType("*/*");
intent.setType(DocumentsContract.Document.MIME_TYPE_DIR);//For API 19+
intent.putExtra(Intent.EXTRA_TITLE, Sdfile.getName());
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
startActivityForResult(intent, 47);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 47) {
if (resultCode != RESULT_OK) return;
File file = new File(Environment.getExternalStorageDirectory(), "myfolder");
copyFile(file, data.getData());
}
Below code is for copy the whole folder to usb storage.
private void copyFile(File src, Uri destUri) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(src));
bos = new BufferedOutputStream(getContentResolver().openOutputStream(destUri));
byte[] buf = new byte[5024];
bis.read(buf);
do {
bos.write(buf);
} while (bis.read(buf) != -1);
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null) bis.close();
if (bos != null) bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
when i am trying to copy the whole folder then it gives error.
Even i direct copy the whole folder to usb storage .
How can i copy whole directory ?

I'm guessing your app does not have the correct permissions. For Android versions below KitKat, you need to declare the permission WRITE_EXTERNAL_STORAGE in your AndroidManifest.xml
<user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Reference: http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE

Related

How to add App specific permissions to Android DocumentProvider

I want to create a file in AppA and then be able to access it from AppB only. I am able to create the file via the DocumentProvider and then access it via StorageClient see examples here. How do I setup the permission on the file in AppA so that only AppB can access it?
Method for file creation in AppA
String s = "kv;ab\nkv1;cd";
try {
byte[] buffer = s.getBytes();
String filename = "myfile.txt";
System.out.println("filename="+filename);
FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE);
fos.write(buffer);
fos.close();
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
Methods for File access in AppB
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
Uri pickerInitialUri= Uri.parse("content://com.example.android.storageprovider.documents/document/root%3Amyfile.txt");
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
startActivityForResult(intent, READ_REQUEST_CODE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
readFileExternalStorage();
}
public String readFileExternalStorage() {
String s = "";
Uri uri1 = Uri.parse("content://com.example.android.storageprovider.documents/document/root%3Amyfile.txt");
try {
InputStream ins = this.getBaseContext().getContentResolver().openInputStream(uri1);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int size;
byte[] buffer = new byte[1024];
while ((size = ins.read(buffer, 0, 1024)) >= 0) {
outputStream.write(buffer, 0, size);
}
ins.close();
buffer = outputStream.toByteArray();
s = new String(buffer);
System.out.println("output=" + s);
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
TextView textview = findViewById(R.id.textView);
textview.setText(s);
return "ok\n" + s;
}
Two probable options-
https://developer.android.com/guide/topics/permissions/defining
Use a shared encryption key with user based salt to encrypt and decrypt stored files on Android

Is it possible to build an android app that installs 3 apk, which are stored inside the app itself?

I'm new to android studio and I'm a beginner. I want to build an app that contains 2 or 3 apk files inside the app itself - not in device storage - and make a single button to prompt to install all of them. Is that possible?!
Use this to save file to storage after requesting necessary permission : Write_External_Storage
private void copyAsset(String filename){
String dirPath =
Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyFiles";
File dir = new File(dirPath);
if(!dir.exists()){
dir.mkdirs();
}
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open( filename);
File outFile = new File(dirPath, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
Toast.makeText(this, "Saved!", Toast.LENGTH_SHORT).show();
} catch (IOException e){
e.printStackTrace();
Toast.makeText(this, "Failed!", Toast.LENGTH_SHORT).show();
} finally {
if (in != null){
try{
in.close();
} catch (IOException e){
e.printStackTrace();
}
}
if (out != null){
try{
out.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
And finally use this to install:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new
File(Environment.getExternalStorageDirectory().getAbsolutePath + "/MyFiles/" +
"appName.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Make sure to request permessions : REQUEST_INSTALL_PACKAGES and READ EXTERNAL STORAGE

file picker throwing ENOENT no such file or directory

i am trying to pick an audio file and save it , but i am getting ENOENT , yet i use the same code with image and it works fine !!!!! \n
i am using file provider to create/save files and it works more than probably .
how can the same code work with images yet not with audio : \n
here is some code examples \n
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0 && resultCode == RESULT_OK) {
Uri resultUri = data.getData();
saveFile(resultUri);
}
}
and to save the file i use :
File dirPath = new File(Environment.getExternalStorageDirectory(),"Moch/WAR/");
File file = new File(dirPath, "notification.mp3");
String sourceFilename = resultUri.getPath();
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
if(!file.exists())
if (!file.createNewFile())
Toast.makeText(notificationsSettings.this,"Unable to make sound File",Toast.LENGTH_LONG).show();
if(file.exists()) {
bis = new BufferedInputStream(new FileInputStream(sourceFilename));
bos = new BufferedOutputStream(new FileOutputStream(file, false));
byte[] buf = new byte[1024];
bis.read(buf);
do {
bos.write(buf);
} while (bis.read(buf) != -1);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null) bis.close();
if (bos != null) bos.close();
mProgressDialog.dismiss();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and this is the doomed error line : \n
/document/audio:266: open failed: ENOENT (No such file or directory)

How to convert file to base64 in Android?

I have enabled the user to select a specific file from his device the extension of the file is .txt , and I'm using MaterialFilePicker library for it , now how to convert this file to string base64 so I can send the file to the server.
if there's another library or another way to do it please recommend me to use it.
this the code I tried but it didn't work out , thanks.
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
//super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSIONS_REQUEST_CODE: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openFilePicker();
} else {
showError();
}
}
}
}
// FILE PICKER
private void checkPermissionsAndOpenFilePicker() {
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
showError();
} else {
ActivityCompat.requestPermissions(this, new String[]{permission}, PERMISSIONS_REQUEST_CODE);
}
} else {
openFilePicker();
}
}
private void showError() {
Toast.makeText(this, "Allow external storage reading", Toast.LENGTH_SHORT).show();
}
private void openFilePicker() {
new MaterialFilePicker()
.withActivity(this)
.withRequestCode(FILE_PICKER_REQUEST_CODE)
.withHiddenFiles(true)
.withTitle("Sample title")
.start();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILE_PICKER_REQUEST_CODE && resultCode == RESULT_OK) {
String path = data.getStringExtra(FilePickerActivity.RESULT_FILE_PATH);
if (path != null) {
Log.d("Path: ", path);
file = new File(path);
fileStr = String.valueOf(file);
Toast.makeText(this, "Picked file: " + file, Toast.LENGTH_LONG).show();
}
}
}
//convert the file path to base64
public static String encodeImage(String path) {
File imagefile = new File(path);
FileInputStream fis = null;
try {
fis = new FileInputStream(imagefile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
if (fis != null) {
try {
fis.close();
if (baos != null)
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//Base64.de
return encImage;
}
First read the file to a byte array, and then use
Base64.encodeToString(byte[], int)
to convert it to a Base64 string.
Try this:
File file = new File("myfile.txt");
//convert file to byte[]
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(file);
bos.close();
oos.close();
byte[] bytearray = bos.toByteArray();
//convert byte[] to file
ByteArrayInputStream bis = new ByteArrayInputStream(bytearray);
ObjectInputStream ois = new ObjectInputStream(bis);
File fileFromBytes = null;
fileFromBytes = (File) ois.readObject();
bis.close();
ois.close();
System.out.println(fileFromBytes);
Note: Don't forget to handle the exception(try/catch)

How to copy image to an existing directory on sd card?

I'm trying to copy an image file with this code:
InputStream fileInputStream = null;
OutputStream fileOutputStream = null;
String inPath = "/storage/emulated/0/Pictures/MyImage.jpg";
String outPath = "/storage/extSdCard/MyFolder/MyImage.jpg";
try {
verifyStoragePermissions(this);
fileInputStream = new FileInputStream(new File(inPath));
File outputFile = new File(outPath);
if (!outputFile.exists()) {
try {
outPutFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
fileOutputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[1024];
int read;
while ((read = fileInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
fileInputStream.close();
fileInputStream = null;
fileOutputStream.flush();
fileOutputStream.close();
fileOutputStream = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
And this is the method for verifying storage permissions on sdk>=23
// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
/**
* Checks if the app has permission to write to device storage
*
* If the app does not has permission then the user will be prompted to grant permissions
*
* #param activity
*/
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
And result is this error which occurs before reaching the buffer line.
Unable to decode stream: java.io.FileNotFoundException: /storage/extSdCard/MyFolder/MyImage.jpg: open failed: ENOENT (No such file or directory)
I have MyFolder on sd card and gallery apps on my device copy images to this directory without any problem.
NOTE: permissions are granted in the manifest (in the correct place before application tag) and inside activity(for skd >=23) .
EDITS:
Implemented suggestion of creating file before fileOutputStream (didn't help).
Lowered the targetSdkVersion to overpass any possible problems related to permissions and still no success.
targetSdkVersion 22
Creating File in this way:
File outFile = new File("/storage/extSdCard", "MyFolder/MyImage.jpg");
also made no result.
I'm testing it on android version 22.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
You need to create the file first, FileOutputStream will throw that exception if the file does not exist FileNotFoundException
File outputFile = new File(outPath);
file.createNewFile();
fileOutputStream = new FileOutputStream(outputFile);
if you are using targetSdkVersion 23 (or higher) in your app gradle file, you need to explicitly request the permission (could be into the onCreate method of the Activity or a button listener method), like this...
private static final int CODE_WRITE_EXTERNAL = 10;
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Log.d(TAG, "onCreate: " + "Show explanation");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_WRITE_EXTERNAL );
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_WRITE_EXTERNAL );
}
} else {
Log.d(TAG, "onCreate: " + "Permission already granted!");
//Call your method to save the file
}
Then you need to implement the next callback method
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case CODE_WRITE_EXTERNAL : {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "onRequestPermissionsResult: Good to go!");
//Call your mehotd here
} else {
Log.d(TAG, "onRequestPermissionsResult: Bad user");
}
}
}
}
This is the way I used SAF to get the job done.
private void newcopyFile(File fileInput, String outputParentPath,
String mimeType, String newFileName) {
DocumentFile documentFileGoal = DocumentFile.fromTreeUri(this, treeUri);
String[] parts = outputParentPath.split("\\/");
for (int i = 3; i < parts.length; i++) { //ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "MyFolder"}
if (documentFileGoal != null) {
documentFileGoal = documentFileGoal.findFile(parts[i]);
}
}
if (documentFileGoal == null) {
Toast.makeText(MainActivity.this, "Directory not found", Toast.LENGTH_SHORT).show();
return;
}
DocumentFile documentFileNewFile = documentFileGoal.createFile(mimeType, newFileName);
InputStream inputStream = null;
OutputStream outputStream = null;
try {
outputStream = getContentResolver().openOutputStream(documentFileNewFile.getUri());
inputStream = new FileInputStream(fileInput);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
if (outputStream != null) {
byte[] buffer = new byte[1024];
int read;
if (inputStream != null) {
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
}
if (inputStream != null) {
inputStream.close();
}
inputStream = null;
outputStream.flush();
outputStream.close();
outputStream = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}

Categories

Resources