Hey i am trying to share the screen shot of a layout. it works very well in all very version which are less than Oreo, but when i am trying to share on Oreo it is giving FileUriExposedException. Please If anyone knows about this issue please solve it as soon as possible.
Here is my code
public Bitmap takeScreenshot() {
View rootView = (FrameLayout)findViewById(R.id.frame_layout).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
public void saveBitmap(Bitmap bitmap) {
imagepath1 = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
FileOutputStream fos;
try {
fos = new FileOutputStream(imagepath1);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
private void shareIt() {
try{
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
Uri uri = Uri.fromFile(imagepath1);
sharingIntent.setType("image/*");
String share_text = "*Create, Share, Download* Valentine Frames and spread love on this \nValentine\uD83D\uDE18\uD83D\uDE18 for free...." +
"\n*Download Now:-* https://play.google.com/store/apps/details?id=technoapps4.valentineframes2019";
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, share_text);
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharingIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(sharingIntent, "Share via"));}
catch ( Exception e)
{
Toast.makeText(this, ""+e, Toast.LENGTH_SHORT).show();
}
AFAIK sharing files by sharing their paths is not allowed anymore since oreo. I got this issue some time ago.
My solution was to share the file content with a content-provider.
Related
To send the email the method for the button is;
public void buttonSendEmailClicked(View view) {
File file = saveFileToShare();
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("application/image");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Check Out MyPic");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Taken With Android!");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
startActivityForResult(Intent.createChooser(emailIntent, "Send mail..."), interstitial_request);
}
The saveFileToShare element is this;
public File saveFileToShare() {
try
{
File fileImage = new File(Environment.getExternalStorageDirectory() + "/DCIM/Camera/attachment.png");
if(!fileImage.exists())
{
fileImage.delete();
}
editorImage.setDrawingCacheEnabled(true);
Bitmap bitmap = editorImage.getDrawingCache();
fileImage.createNewFile();
FileOutputStream ostream = new FileOutputStream(fileImage);
bitmap.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
editorImage.invalidate();
editorImage.setDrawingCacheEnabled(false);
return fileImage;
}
catch (Exception e)
{
System.out.print(e);
e.printStackTrace();
return null;
}
}
Saving the image works fine, the save code is;
public void buttonSaveImageClicked(View view) throws IOException {
editorImage.setDrawingCacheEnabled(true);
Bitmap bitmap = editorImage.getDrawingCache();
SaveLayoutToFile saveImage = new SaveLayoutToFile(this, bitmap, editorImage);
String filePath = Environment.getExternalStorageDirectory() + "/DCIM/Camera/wonkydog";
saveImage.execute(filePath);
}
I need to set the email code to grab the image and attach to email.
At the moment when I press the email button it just returns to the title screen without doing anything else.
If I comment out this line
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
Then it opens the mail send dialogue, but without attachment of course...
I found the answer, rather than using the emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
I replaced it with;
emailIntent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(EditorActivity.this, "com.myapp.myappname.provider", file));
It now works correctly!
I have checked the uri, the file saved is a bitmap and its returning file. But the image which shows during sharing is not valid. Gmail says it could not attach the attachment, messages app could not load the image.
Text sharing is working fine.
I am new to Android and is having problem sharing image through share intent. I have googled alot, tried various things but still could not find the solution.
public static void shareWallpaper(Context context, int wallpaperResourceId) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), wallpaperResourceId);
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/wallpaper" + String.valueOf(wallpaperResourceId) + ".jpg";
OutputStream out = null;
File file = new File(path);
try {
out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(file.getPath()));
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.startActivity(Intent.createChooser(shareIntent, "برنامه مورد نظر خود را انتخاب کنید"));
}
I am trying to programmatically change a ringtone in API 23.
I have looked at a lot of examples on Stack Overflow and they all seem to "work" (i.e. not crash) but they do not "work" as in the mp3 doesn't become the ringtone - instead the ringtone becomes simply zero noise. So obviously /something/ happened. (no crash, now no ringtone noise)
I have split this off into a small side project to try to isolate it because it's driving me up the wall - I hope maybe you guys can see something I can't!
I have:
placed the mp3 in \res\raw
I have verified I can play the mp3 fine with this code
MediaPlayer mPlayer = MediaPlayer.create(me, R.raw.meepmeep);
mPlayer.start();
added <uses-permission android:name="android.permission.WRITE_SETTINGS"/> to the manifest
managed the api 22 permission scenario in java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.System.canWrite(this)) {
new AlertDialog.Builder(this)
.setMessage("Please Assign Meep Meep Write Permissions")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (Exception e) {
Log.e("MainActivity", "error starting permission intent", e);
}
}
})
.show();
return;
}
used a method to carefully fetch the mp3 path from the assets folder
public String LoadFile(String fileName, boolean loadFromRawFolder) throws IOException
{
InputStream iS;
if (loadFromRawFolder)
{
int rID = resources.getIdentifier("meep.example.com.meep:raw/"+fileName, null, null);
iS = resources.openRawResource(rID);
}
else
{
iS = resources.getAssets().open(fileName);
}
byte[] buffer = new byte[iS.available()];
iS.read(buffer);
ByteArrayOutputStream oS = new ByteArrayOutputStream();
oS.write(buffer);
oS.close();
iS.close();
return oS.toString();
}
tried to carefully copy the file to the local storage (as a desperate attempt to get it to work as well as tried to assign it from the raw assets lib
String path = "";
try {
LoadFile("meepmeep", true);
} catch (IOException e) {
//display an error toast message
Toast toast = Toast.makeText(me, "File: not found!", Toast.LENGTH_LONG);
toast.show();
}
//copy file to device
File newSoundFile = new File(path);
//Uri mUri = Uri.parse("android.resource://meep.example.com.meep/R.raw.meepmeep");
Uri mUri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
ContentResolver mCr = getContentResolver();
AssetFileDescriptor soundFile;
try {
soundFile= mCr.openAssetFileDescriptor(mUri, "r");
try {
byte[] readData = new byte[1024];
FileInputStream fis = soundFile.createInputStream();
FileOutputStream fos = new FileOutputStream(newSoundFile);
int i = fis.read(readData);
while (i != -1) {
fos.write(readData, 0, i);
i = fis.read(readData);
}
fos.close();
} catch (IOException io) {
}
} catch (FileNotFoundException e) {
soundFile=null;
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "Meep Meep");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, newSoundFile.length());
values.put(MediaStore.Audio.Media.ARTIST, "RoadRunner");
//values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
Uri uri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
Uri newUri = mCr.insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(
me,
RingtoneManager.TYPE_RINGTONE,
newUri
);
}
catch (Throwable t){
setMessage("meepmeep error");
}
setMessage("meepmeep set");
}
but nothing seems to work. It always fails becuase either soundFile= mCr.openAssetFileDescriptor(mUri, "r"); returns null or if I decline to use that code block and try to change ringtone direct from \res\raw\ folder then it simply gives a blank sound for ringtone.
I am totally stuck for ideas?
I have an app that allow user to upload a photo on wall.
The code works well for the majority of users, but I have reported that the application crashes sometimes when uploading photo.
The problem is not in taking the pictures from the camera, but it is when you have to take the path of the picture.
The version of Android that is causing this problem is 4.4.2, but I do not understand how to fix it.
post some code:
activityResult:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == CAMERA_PIC_REQUEST) {
try {
//picUri is a global variable Uri
picUri = data.getData();
cropImage();
} catch (Exception e) {
e.printStackTrace();
}
}
else if(requestCode == PIC_CROP) {
try{
//thumbnail is a global variable Bitmap
thumbnail = MediaStore.Images.Media.getBitmap(context.getContentResolver(), cropImageUri);
setImage();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
hot to crop image:
public void cropImage() {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
//indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
//set crop properties
cropIntent.putExtra("crop", "true");
//indicate aspect of desired crop
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("scale", true);
//indicate output X and Y
cropIntent.putExtra("outputX", 700);
cropIntent.putExtra("outputY", 700);
//retrieve data on return
cropIntent.putExtra("return-data", false);
File f = createNewFile("CROP_");
try{
f.createNewFile();
}
catch (IOException e) {
e.printStackTrace();
}
//cropImageUri is a global variable Uri
cropImageUri = Uri.fromFile(f);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri);
//start the activity - we handle returning in onActivityResult
startActivityForResult(cropIntent, PIC_CROP);
}
catch(ActivityNotFoundException anfe){
anfe.printStackTrace();
}
}
create new File:
private File createNewFile(String prefix) {
if (prefix== null) {
prefix="IMG_";
}
else if("".equalsIgnoreCase(prefix)) {
prefix="IMG_";
}
File newDirectory = new File(Environment.getExternalStorageDirectory()+"/mypics/");
if (!newDirectory.exists()) {
if (newDirectory.mkdir()) {
}
}
File file = new File(newDirectory,(prefix+System.currentTimeMillis()+".jpg"));
if (file.exists()) {
file.delete();
try {
file.createNewFile();
}catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
then when a user click on "send" method preUploadImage is called:
public void preUploadImage() {
UploadImage uploadImage = new UploadImage();
Uri newUri = getImageUri(thumbnail);
try{
// System.out.println("uri = "+picUri);
uploadImage.upload(getRealPathFromURI(newUri));
}
catch (IOException e) {
e.printStackTrace();
}
}
public Uri getImageUri(Bitmap inImage) {
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
and in the last row the error appears.
return Uri.parse(path);
this row cause a NullPointerException
java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.<init>(Uri.java:468)
at android.net.Uri$StringUri.<init>(Uri.java:458)
at android.net.Uri.parse(Uri.java:430)
at com.delsorboilario.verdebio.ScriviDomanda.getImageUri(ScriviDomanda.java:584)
at com.delsorboilario.verdebio.ScriviDomanda.preUploadImage(ScriviDomanda.java:608)
at com.delsorboilario.verdebio.ScriviDomanda$6$4$2.run(ScriviDomanda.java:292)
I have not attempted to use insertImage(), and in this case, it is not quite clear why you would need it.
Primarily, it seems like you are looking to upload the photo. For that, all you need is the File that you created in createNewFile(). If you are uploading it yourself (e.g., HttpUrlConnection, some third-party library), you should be able to just use the File or an InputStream on it. Even if the upload code really needs a Uri, you can try Uri.fromFile() to get a Uri from your File and see if that works.
Where MediaStore does come into play is making your file be indexed and therefore accessible to apps (ones that query the MediaStore for images) and to users (via their MTP connection through their USB cable). MediaScannerConnection and its static scanFile() method are a fairly straightforward way to get the file indexed. Just make sure your file is fully written to disk first (e.g., if you are writing the file yourself, call getFD().sync() on your FileOutputStream after flush() and before close()).
Looks like MediaStore.Images.Media.insertImage(context.getContentResolver(), inImage, "Title", null); return null.
Form the documentation of MediaStore.Images.Media
Insert an image and create a thumbnail for it.
Parameters
cr The content resolver to use
source The stream to use for the image
title The name of the image
description The description of the image
Returns The URL to the newly created image, or null if the image
failed to be stored for any reason
The requirements: ensure that the PDF document is deleted from the device after the user has left the PDF viewing screen
The problem: on certain devices (Samsung 4.4.2 and Samsung 4.1.2 for sure, but not Asus 4.2.1) only the first time that the PDF is requested after restarting the application an error message is displayed stating "This document cannot be opened". Thereafter the PDF will load normally. I'm thinking this is a timing issue due to processes that need to be started the first time, but are running after the first attempted load.
The code: note that createFile() is called first, then startActivityForIntentResult()
private File file;
private ArrayList<Uri> uriList = new ArrayList<Uri>();
private void createFile() {
int fileNameLength = pdfFileName[0].length();
String fileName = pdfFileName[0].substring(0, fileNameLength - 4) + DateTime.now();
String fileExtension = pdfFileName[0].substring(fileNameLength - 4, fileNameLength);
byte[] content = Base64.decodeBase64(pdfData[0].getBytes());
BufferedOutputStream outputStream = null;
try {
File path = new File(getExternalFilesDir(null).getAbsolutePath(), "temp");
if (!path.exists()) {
path.mkdirs();
}
file = new File(path, fileName + fileExtension);
outputStream = new BufferedOutputStream(new FileOutputStream(file));
outputStream.write(content);
file.deleteOnExit();
uriList.add(Uri.fromFile(file));
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static int REQUEST_CODE = 1;
private Intent intent;
private void startActivityForIntentResult() {
if (file.exists()) {
Uri targetUri = uriList.get(0);
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(targetUri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
try {
startActivityForResult(intent, REQUEST_CODE);
}
catch (ActivityNotFoundException e) {
toastTitle = "Error Displaying PDF";
toastMessage = "Please make sure you have an application for viewing PDFs installed on your device and try again.";
toast = new GenericCustomToast();
toast.show(toastTitle, toastMessage, QueryForPDF.this);
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == RESULT_CANCELED && requestCode == REQUEST_CODE) {
if(!file.delete()) {
file.delete();
}
}
searchAgain();
}
#Override
public void onBackPressed() {
super.onBackPressed();
if(!file.delete()) {
file.delete();
}
searchAgain();
}
#Override
public void onStop() {
super.onStop();
if(!file.delete()) {
file.delete();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if(!file.delete()) {
file.delete();
}
}
EDIT: I have also tried implementing a callback to be absolutely certain that createFile() has finished it's work. I even tried adding delays (of different time increments) as well as adding (the completely unnecessary) flags for Intent.FLAG_GRANT_READ_URI_PERMISSION, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION.
I still don't know why this works, but here's the solution in case anyone else runs into this issue:
It's the directory where the file is created. For some reason on the two Samsung devices there was something different in how the files were either accessed or created versus the Asus device. So File path = new File(getExternalFilesDir(null).getAbsolutePath(), "temp"); becomes File path = new File(getExternalCacheDir().getAbsolutePath()); and the problem goes away.