if (Utils.isPackageInstalled(getContext(), "com.whatsapp")) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
Bitmap bitmap = Utils.screenShotBitmap(getActivity());
Utils.saveImage(getActivity(), bitmap, bet.getID() + ".jpeg");
File file = new File(getActivity().getFilesDir(), bet.getID() + ".jpeg");
if (file.exists()) {
Log.i("share", "file exists");
Log.i("share", Uri.fromFile(file).toString());
}
sendIntent.putExtra(Intent.EXTRA_TEXT, "Share text");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
sendIntent.setType("image/*");
sendIntent.setPackage("com.whatsapp");
startActivity(sendIntent);
}
// ...
public static Bitmap screenShotBitmap(Activity activity) {
return Falcon.takeScreenshotBitmap(activity);
}
public static void saveImage(Context context, Bitmap b, String name){
FileOutputStream out;
try {
out = context.openFileOutput(name, Context.MODE_PRIVATE);
b.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Log-Output:
03-25 17:13:24.328 26417-26417/x.x.x I/share: file exists
03-25 17:13:24.328 26417-26417/x.x.x I/share: file:///data/data/x.x.x/files/4b00abc2-7aae-4234-945b-59905306ad4a.jpeg
Result:
Bitmap bitmap = Utils.screenShotBitmap(getActivity()); seems to work fine and return a correct Bitmap, because I can share it without problems to facebook.
because I can share it without problems to facebook
Not with that code.
You are writing the file to internal storage. Neither Facebook nor WhatsApp has access to your portion of internal storage. Plus, using file: Uri values is being phased out.
The correct long-term answer is for you to use a ContentProvider to publish the bitmap, such as using FileProvider. In the short term, you can probably get away with writing to external storage, such as getExternalFilesDir().
Also note that ACTION_SEND recipients do not need to honor both EXTRA_TEXT and EXTRA_STREAM, but only one or the other.
Related
I have a Relative layout and Textview on it. Then I convert that relative layout to bitmap image and save in directory.
The problem is when I am sharing the image, in most of app, I found correct image but in case of whatsapp when I am sharing through whatsapp the preview of sharing image is showing me old one until I close the app. Why it's not getting update and when I share the image on whatsapp, preview is old one and the image goes right one. This works fine in FB, Gmail etc...
This is the below code for converting and saving converted bitmap image in file system (directory)
This is for creating Direcory:
File dir = null;
String directorySubPath = "Android/data/com.domainname.appname/sharedResource/";
String imageNameForSave = "/qqq.png";
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
Toast.makeText(this, "Your device doesn't have external storage.", Toast.LENGTH_SHORT).show();
return;
}
else
{
Log.d("SD", "YES", null);
dir = new File(Environment.getExternalStorageDirectory()+File.separator+directorySubPath);
if (!dir.exists()){
dir.mkdirs();
}
else {
Log.d("Q-Design:", "Already created", null);
}
}
This is for code convert layout to bitmap image & save.
rLayout.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(rLayout.getDrawingCache());
FileOutputStream out = new FileOutputStream(dir+imageNameForSave);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
rLayout.setDrawingCacheEnabled(false);
This is for SHARING that image via Intent:
Uri uri = Uri.parse("file:///" + dir + imageNameForSave);
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("image/jpg");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Test Mail");
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Data Shared with you...");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(shareIntent, "Share via:"));
Use a dynamic name in String imageNameForSave
Ex. String imageNameForSave = "/qqq" + mydate + ext;
Developing Android email plugin for Unity. I have a screenshot in the files/ folder of the app, I want to attach to mail. As it turned out, I cannot attach from there directly. I implemented a FileProvider, but it turned out that it exist only above 4.0.
So I implemented the suggested workaround, to save it to external storage, then attach from there. Saving seems work, even reading seems work, but still, Gmail says "Can't attach empty file". Also When launching email intent, I have an error message, like:
E/HwEmailTag( 7327): AttachmentUtilities->inferMimeTypeForUri->Unable to determine MIME type for uri=/storage/emulated/0/com.eppz.plugins_screenshot.jpg
I tried application/image, image/jpg as intent.setType(), still the same, while Gmail says the file is empty.
Is this something with emulated external storage /storage/emulated/0/? The device has no SD card, but I've read that getExternalStorage() returns a shared / public place for files in such cases either.
It should work. Should I remove dots from filename? Hope not. Here's the corresponding code:
String saveImageAtPathToExternalStorage(String imagePath)
{
Log.i(TAG, "saveImageAtPathToExternalStorage(...)");
// Create bitmap.
File imageFile = new File(imagePath);
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath(), new BitmapFactory.Options());
// Output.
String outputFileName = _unityPlayerActivity.getPackageName()+"_screenshot.jpg";
String externalStorageDirectory = Environment.getExternalStorageDirectory().toString();
File outputImageFile = new File(externalStorageDirectory, outputFileName);
String outputImagePath = outputImageFile.getAbsolutePath();
if (outputImageFile.exists()) outputImageFile.delete(); // Delete if existed
try
{
// Write JPG.
FileOutputStream outputStream = new FileOutputStream(outputImageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
Log.i(TAG, "Image written to `"+outputImagePath+"`");
}
catch (Exception e)
{ e.printStackTrace(); }
// Return with output path.
return outputImagePath;
}
public void openMailComposer(String to, String subject, String body, int isHTML, String attachmentImagePath)
{
Log.i(TAG, "openMailComposer(...)");
// Attachment image.
File attachmentImageFile = new File(attachmentImagePath);
if (attachmentImageFile.exists() == false)
{
Log.i(TAG, IMAGE_NOT_FOUND);
SendUnityMessage(OPEN_MAIL_COMPOSER_CALLBACK_METHOD_NAME, IMAGE_NOT_FOUND);
return;
}
// Save to external first.
String externalImagePath = saveImageAtPathToExternalStorage(attachmentImagePath);
final Uri externalImageUri = Uri.parse(externalImagePath);
Log.i(TAG, "externalImageUri `"+externalImageUri+"`");
// Intent.
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, body);
if (isHTML == 1) intent.putExtra(Intent.EXTRA_HTML_TEXT, body);
// Attach.
intent.putExtra(Intent.EXTRA_STREAM, externalImageUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(Intent.createChooser(intent, "Send email"), OPEN_MAIL_COMPOSER_REQUEST_CODE);
}
I'm relatively new to Android development, and really want to believe, but having all this hassle compared to having a single line for this in iOS is quiet distressing.
I'm running this on a Huawei MediaPad (TT1 7.0), Android 4.4.2, and I want it to run about Android 2.3+ basically (why I refused using FileProvider earlier).
I have used com.nostra13.universalimageloader to load image. Inside the standard ImageAdapter in a ViewPager, there is a share button to share the bitmap. The code is as follows:
Code:
#Override
public Object instantiateItem(ViewGroup view, int position)
{
....
#Override
public void onLoadingComplete(String imageUri, View view, final Bitmap loadedImage)
{
spinner.setVisibility(View.GONE);
btn_share = (ImageButton) imageLayout.findViewById(R.id.btn_share);
btn_share.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Shining Card";
File dir = new File(file_path);
if (!dir.exists()) dir.mkdirs();
File file = new File(dir, "to share");
FileOutputStream fOut;
try
{
fOut = new FileOutputStream(file);
loadedImage.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
}
catch (Exception e)
{
e.printStackTrace();
Constants.custom_toast(getActivity(), "Error when sharing", "");
}
Uri uri = Uri.fromFile(file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent, "Share Cover Image"));
}
});
}
Question:
The problem lies on sharing the image.
Share via whatsapp
Sharing the first image via whatsapp, the image can be shared successfully to others. Continues with sharing second image it also works successfully.
However, if the sharing of the first image is cancelled in whatsapp and return to the app, and then choose another image to share in whatsapp, the preview in whatsapp will remain as the first image, though if ignore it and continue to share whatsapp will actually share the new image. (i.e. there is a preview problem) (using other app to share image perform the same, preview in whatsapp does not go wrong)
Share via gmail
Sharing the image as attachment via gmail, the image cannot be previewed nor opened.
I've seen several exemples but still don't get why, when I'm editing the mail I see the .xml attached but when I receive ther's no attachment!
Here is my code
File f = new File("data/data/xxx/files/xxx.xml");
Boolean b1 = f.exists();
Boolean b2 = f.canRead();
if (b1 && b2) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(Intent.EXTRA_EMAIL, "");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" +
f.getAbsolutePath()));
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "XXX");
sendIntent.putExtra(Intent.EXTRA_TEXT, R.string.mail_body);
startActivity(Intent.createChooser(sendIntent, "Email:"));
} else {
...
Ah, only a detail...when I choose the app to send there is no subject or body, even if I wrote putExtra(Intent.EXTRA_SUBJECT) and putExtra(Intent.EXTRA_TEXT), but that's a detail...
Edit: I just debuged my intent: it says "NOT CACHED" in value of the stream, how to solve it?
You can't attach a file from internal storage directly for some security purpose, hence first you have to copy that file from internal to external directory and then mail after that if you want you can delete that file from external storage in onActivityResult() method.
Here's a code :
private File copyFileToExternal(String fileName) {
File file = null;
String newPath = Environment.getExternalStorageState()+"/folderName/";
try {
File f = new File(newPath);
f.mkdirs();
FileInputStream fin = openFileInput(fileName);
FileOutputStream fos = new FileOutputStream(newPath + fileName);
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = fin.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fin.close();
fos.close();
file = new File(newPath + fileName);
if (file.exists())
return file;
} catch (Exception e) {
}
return null;
}
Method to Email:
private void sendEmail(String email) {
File file = new File(Environment.getExternalStorageState()+"/folderName/" + fileName+ ".xml");
Uri path = Uri.fromFile(file);
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
String to[] = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, message);
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."),
1222);
}
and then
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1222) {
File file = new File(Environment.getExternalStorageState()+"/folderName/" + fileName+ ".xml");
file.delete();
}
}
Call this method like this:
copyFileToExternal(filename + ".xml");
sendEmail(EmailId);
I've seen several exemples but still don't get why, when I'm editing the mail I see the .xml attached but when I receive ther's no attachment!
First, third-party apps cannot read internal storage of your app.
Second, that might not be the right path to internal storage of your app. Never hardcode paths. Your app will fail for secondary accounts and restricted profiles on Android 4.2 tablets, for example. Always use a method, like getFilesDir(), to get at your portion of internal storage.
You will need to either copy your file to external storage, or better yet, use FileProvider to serve up your file from internal storage via a content:// Uri.
I have an ImageView with a share intent( which works great, brings up all the apps I can share the image with), however, I can not share the photo because it has no path on my phone. How do I go about saving the ImageView on my phone? Below is my code.
public void taptoshare(View v)
{
View content = findViewById(R.id.myimage);
content.setDrawingCacheEnabled(true);
Bitmap bitmap = content.getDrawingCache();
File file = new File("/DCIM/Camera/image.jpg");
try
{
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, ostream);
ostream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri phototUri = Uri.parse("/DCIM/Camera/image.jpg");
shareIntent.setData(phototUri);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, phototUri);
startActivity(Intent.createChooser(shareIntent, "Share Via"));
}
}
UPDATE
Ok, so I figured it out. Now I have a new question, how would I go about saving this image to a new folder?
When saving and loading, you need to get the root path of the system, first. This is how I'd do it.
File root = Environment.getExternalStorageDirectory();
File cachePath = new File(root.getAbsolutePath() + "/DCIM/Camera/image.jpg");
I've come across a couple solutions which are not solving this problem.
Here is a solution that worked for me. One gotcha is you need to store the images in a shared or non app private location (http://developer.android.com/guide/topics/data/data-storage.html#InternalCache)
Many suggestions say to store in the Apps "private" cache location but this of course is not accessable via other external applications, including the generic Share File intent which is being utilised. When you try this, it will run but for example dropbox will tell you the file is no longer available.
/* STEP 1 - Save bitmap file locally using file save function below. */
localAbsoluteFilePath = saveImageLocally(bitmapImage);
/* STEP 2 - Share the non private Absolute file path to the share file intent */
if (localAbsoluteFilePath!=null && localAbsoluteFilePath!="") {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri phototUri = Uri.parse(localAbsoluteFilePath);
File file = new File(phototUri.getPath());
Log.d("file path: " +file.getPath(), TAG);
if(file.exists()) {
// file create success
} else {
// file create fail
}
shareIntent.setData(phototUri);
shareIntent.setType("image/png");
shareIntent.putExtra(Intent.EXTRA_STREAM, phototUri);
activity.startActivityForResult(Intent.createChooser(shareIntent, "Share Via"), Navigator.REQUEST_SHARE_ACTION);
}
/* SAVE IMAGE FUNCTION */
private String saveImageLocally(Bitmap _bitmap) {
File outputDir = Utils.getAlbumStorageDir(Environment.DIRECTORY_DOWNLOADS);
File outputFile = null;
try {
outputFile = File.createTempFile("tmp", ".png", outputDir);
} catch (IOException e1) {
// handle exception
}
try {
FileOutputStream out = new FileOutputStream(outputFile);
_bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
} catch (Exception e) {
// handle exception
}
return outputFile.getAbsolutePath();
}
/* STEP 3 - Handle Share File Intent result. Need to remote temporary file etc. */
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// deal with this with whatever constant you use. i have a navigator object to handle my navigation so it also holds all mys constants for intents
if (requestCode== Navigator.REQUEST_SHARE_ACTION) {
// delete temp file
File file = new File (localAbsoluteFilePath);
file.delete();
Toaster toast = new Toaster(activity);
toast.popBurntToast("Successfully shared");
}
}
/* UTILS */
public class Utils {
//...
public static File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file =
new File(Environment.getExternalStorageDirectory(), albumName);
if (!file.mkdirs()) {
Log.e(TAG, "Directory not created");
}
return file;
}
//...
}
I hope that helps someone.