How to add App specific permissions to Android DocumentProvider - android

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

Related

Image not showing when passed as an intent extra

I'm trying to pass the screenshot of screen with an explicit intent but the screen shows black screenshot(refer image here). As soon as i click share, a toast appears saying sending failed. Here's the code to capture screenshot and send it to other app:
public void getScreenShot(View view) {
View screenView = view.getRootView();
screenView.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
screenView.setDrawingCacheEnabled(false);
f = new File(this.getFilesDir(), "screenshotFile");
try {
if (!f.exists())
f.createNewFile();
} catch (IOexception e) {
e.printStackTrace();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, bos);
byte[] bitmapdata = bos.toByteArray();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
fos.write(bitmapdata);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
This code sends the data to whatsapp:
public void shareWhatsapp(View view) {
try {
myVib.vibrate(50);
getScreenShot(view);
//String fileName = "screenshotFile";
//Bitmap bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
try {
intent.setPackage("com.whatsapp");
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "App not installed", Toast.LENGTH_SHORT).show();
}
//TODO: APP CAN CRASH HERE
if (position > 0) {
try {
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f);
} catch (Exception e) {
e.printStackTrace();
} finally {
intent.putExtra(Intent.EXTRA_TEXT, Titles.get(position - 1) + ": " + Links.get(position - 1)); //position problems
}
} else {
try {
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f);
} catch (Exception e) {
e.printStackTrace();
} finally {
intent.putExtra(Intent.EXTRA_TEXT, Titles.get(0) + ": " + Links.get(0)); //position problems
}
}
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
Can someone help me with this?
First, you are writing the file to internal storage. Third-party apps do not have access to your app's internal storage.
Second, you are using Uri.fromFile(), which is starting to be discontinued.
Your safest long-term course of action is to have a ContentProvider serve your file from its location on internal storage, then use a Uri associated with that ContentProvider.

how to copy directory (folder) to usb storage

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

How to select an audio file and upload it to parse in android

I opened the music player to select an audio file using this code
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent_upload = new Intent();
intent_upload.setType("audio/*");
intent_upload.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent_upload,1);
}
});
I called the uploadAudioToParse method inside OnActivityResult()
#Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
if(requestCode == 1){
if(resultCode == RESULT_OK){
//the selected audio.
Uri uri = data.getData();
File abc=new File(uri.toString());
ParseObject ob=new ParseObject("songs");
uploadAudioToParse(abc,ob,"song");
}
}
super.onActivityResult(requestCode, resultCode, data);
}
And this is my uploadAudioToParse method.
private ParseObject uploadAudioToParse(File audioFile, ParseObject po, String columnName){
if(audioFile != null){
Log.d("EB", "audioFile is not NULL: " + audioFile.toString());
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(audioFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int read;
byte[] buff = new byte[1024];
try {
assert in != null;
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
byte[] audioBytes = out.toByteArray();
// Create the ParseFile
ParseFile file = new ParseFile(audioFile.getName() , audioBytes);
po.put(columnName, file);
// Upload the file into Parse Cloud
file.saveInBackground();
po.saveInBackground();
}
return po;
}
is the file conversion method correct?

save multiple images from url into internal storage in android

i am using this method to get images from url and i am downloading more than one image the varable below called "name" is an array of names of the images .i want to be able to store all images whos name is in the array thats why i kept the url like that.it seems to work well but i have having problem selecting only one picture out or them.
this is the code to save images
String fileName="code";
try {
URL url = new URL("http://10.0.2.2/picure/"+name+".jpg");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
Bitmap bm = BitmapFactory.decodeStream(is);
FileOutputStream fos = getActivity().openFileOutput(fileName, Context.MODE_PRIVATE);
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, outstream);
byte[] byteArray = outstream.toByteArray();
fos.write(byteArray);
fos.close();
Toast.makeText(getActivity()," connected", Toast.LENGTH_LONG).show();
} catch(Exception e) {
}
this is the code to collect images
String path = mContext.getFilesDir().toString();
String fileName = "code";
if (fileName != null && !fileName.equals("")) {
Bitmap bMap = BitmapFactory.decodeFile(path + "/" + fileName);
if (bMap != null) {
category_logo.setImageBitmap(bMap);
}
}
i know the names of the images i saved so how do i select that one specifically
For get all images use a Asynctask, this code can download images in cache directory of the app:
class ImageDownloader extends AsyncTask<String, Void, File> {
String imageurl;
String name;
Context ctx;
public ImageDownloader(Context context, String url, String fileName) {
this.imageurl = url;
this.name = fileName;
this.ctx = context;
}
#Override
protected File doInBackground(String... urls) {
Bitmap mIcon;
File cacheDir = ctx.getCacheDir();
File f = new File(cacheDir, name);
try {
InputStream in = new java.net.URL(imageurl).openStream();
mIcon = BitmapFactory.decodeStream(in);
try {
FileOutputStream out = new FileOutputStream(
f);
mIcon.compress(
Bitmap.CompressFormat.JPEG,
100, out);
out.flush();
out.close();
return f;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(File result) {
super.onPostExecute(result);
Toast.makeText(ctx," connected " + name, Toast.LENGTH_LONG).show();
}
}
}
For call the asynctask, you need use a FOR for get all names and url of the image:
new ImageDownloader(getBaseContext(),url[i],name[i]).execute();
You can edit the doInBackground with your code, but the HTTPConnection that you use is deprecated in API 22, please use the example above, you can change the directory.
And sorry for the code, you can reformat later.
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CODE_MULTIPLE_IMG_GALLERY && resultCode==RESULT_OK){
ClipData clipData = data.getClipData();
if (clipData!=null){
File folderPath = new File(getIntent().getStringExtra("folderpath"));
for (int i = 0;i< clipData.getItemCount();i++){
ClipData.Item item = clipData.getItemAt(i);
Uri uri = item.getUri();
Bitmap selectedImage = loadFromUri(uri);
File imagePath = new File(folderPath,System.currentTimeMillis()+".jpg");
try {
outputStream = new FileOutputStream(imagePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
selectedImage.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
Log.d("uri",uri.toString());
imageModelList.add(new ImageModel(uri.toString()));
}
imagesAdapter.notifyDataSetChanged();
Toast.makeText(ImageDetailActivity.this, "Added Successfully!", Toast.LENGTH_SHORT).show();
}
}
}
public Bitmap loadFromUri(Uri photoUri) {
Bitmap image = null;
try {
// check version of Android on device
if(Build.VERSION.SDK_INT > 27){
// on newer versions of Android, use the new decodeBitmap method
ImageDecoder.Source source = ImageDecoder.createSource(this.getContentResolver(), photoUri);
image = ImageDecoder.decodeBitmap(source);
} else {
// support older versions of Android by using getBitmap
image = MediaStore.Images.Media.getBitmap(this.getContentResolver(), photoUri);
}
} catch (IOException e) {
e.printStackTrace();
}
return image;
}

Upload photo from gallery or take from camera in Webview

My application is webbased and need to upload photos, website have a file input button, i made it work with this
wv = new WebView(this);
wv.setWebViewClient(new WebViewClient());
wv.getSettings().setJavaScriptEnabled(true);
wv.getSettings().setAllowFileAccess(true);
wv.setWebChromeClient(new WebChromeClient()
{
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MainActivity.this.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MainActivity.FILECHOOSER_RESULTCODE );
}
but it shows just gallery to pick photos, i need to take from camera at the same time.
i tried this solution Upload camera photo and filechooser from webview INPUT field but its only opening camera, not uploading taken photo
In your example
wv.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView v, String url) {
if (url.startsWith("testzapp:")) {
//do whatever action you had intended
}
}
}
here is my solution
if (url.startsWith("xxx")) {
String[] falid = url.split(":");
falidi = Integer.parseInt(falid[1]);
Intent intent = new Intent(
"android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, TAKE_PICTURE);
return true;
}
public void onActivityResult(int requestCode, int resultCode,
final Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == TAKE_PICTURE) {
try {
Bitmap photo = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
Random randomGenerator = new Random();
randomGenerator.nextInt();
newimagename = falidi + "_" + randomGenerator.nextInt()
+ ".jpg";
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + newimagename);
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// write the bytes in file
FileOutputStream fo = null;
try {
fo = new FileOutputStream(f.getAbsoluteFile());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fo.write(bytes.toByteArray());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String uri = f.getAbsolutePath();
// this is the url that where you are saved the
// image
File fx = new File(uri);
Bitmap bitmap = BitmapFactory.decodeFile(fx.getPath());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 30, stream);
byte[] byte_arr = stream.toByteArray();
String image_str = Base64.encodeToString(byte_arr,
Base64.DEFAULT);
client = new DefaultHttpClient();
HttpPost post = new HttpPost(
"http://www.xxx.com/android/library/image.php?name="
+ newimagename);
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
pairs.add(new BasicNameValuePair("image", image_str));
try {
post.setEntity(new UrlEncodedFormEntity(pairs));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Candemir
new ResultTask().execute(new HttpPost[] { post });
// Candemir
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

Categories

Resources