I'm trying to implement the "share" button. It is necessary to send a picture.
That's what I'm doing:
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
File outputDir = context.getCacheDir();
File outputFile = null;
try {
outputFile = File.createTempFile("temp_", ".jpg", outputDir);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(outputFile));
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent,
getResources().getText(R.string.send_via)));
but I get a message saying that it's impossible to upload an image. What's the matter?
First, third-party apps have no rights to access files in your portion of internal storage.
Second, on Android 7.0+, you cannot use file Uri values, such as those returned by Uri.fromFile().
To solve both problems, use FileProvider to make the image available to other apps. Use FileProvider.getUriForFile() instead of Uri.fromFile(), and be sure to add FLAG_GRANT_READ_URI_PERMISSION to the Intent.
This sample app demonstrates using FileProvider with third-party apps (for ACTION_IMAGE_CAPTURE and ACTION_VIEW, but the same technique will work for ACTION_SEND).
Related
I'm relatively new to android, and I'm trying to modify an android app such that it downloads a profile picture (preferably in PNG) from a URL, and saves it in the com.companyName.AppName.whatever/files. It should be noted that the app was initially created in Unity, and just built and exported.
Here's my initial code:
URL url = null;
try {
url = new URL(playerDO.getProfileURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
InputStream input = null;
try {
input = url.openStream();
} catch (IOException e) {
e.printStackTrace();
}
String fileName = playerDO.getId() + ".png";
FileOutputStream outputStream = null;
try {
outputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
byte[] buffer = new byte[256];
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
EDIT: Here's my other code, as suggested by #Ashutosh Sagar
InputStream input = null;
Bitmap image = null;
try {
input = url.openStream();
image = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
String fileName = playerDO.getId() + ".png";
FileOutputStream outputStream = null;
File myDir = getFilesDir();
try {
Log.wtf("DIRECTORY", myDir.toString());
File imageFile = new File(myDir, fileName);
if (!imageFile.exists()){
imageFile.createNewFile();
Log.wtf("ANDROID NATIVE MSG: WARN!", "File does not exist. Writing to: " + imageFile.toString());
}
outputStream = new FileOutputStream(imageFile, false);
image.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
Log.wtf("AWWW CRAP", e.toString());
}
}
(It doesn't write either).
Unfortunately, I've had several problems with this. My primary issue is that when it (on the cases that it does) runs, it actually doesn't save anything. I'll go and check com.companyName.AppName.whatever/files directory only to find no such .png file. I will also need it to overwrite any existing files of the same name, which is hard to check when it doesn't work.
My secondary issue is that it fails to take into account delays in internet connection. Although I've put in enough try-catch clauses to stop it from crashing (as it used to), the end result is that it also doesn't save.
How can I improve upon this? Anything I'm missing?
EDIT:
Printing out the directory reveals it should be in:
/data/user/0/com.appName/files/5965e9e4a0f0463853016e2b.png
However, using ES File explorer, the only thing remotely close to that is
emulated/0/Android/data/com.appName/files/
Are they the same directory?
try this first get bitmap image from url
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(url).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.d("Error", e.getStackTrace().toString());
}
and to save bitmap image please check the ans of GoCrazy
Try this
void getImage(String string_url)
{
//Generate Bitmap from URL
URL url_value = new URL(string_url);
Bitmap image =
BitmapFactory.decodeStream(url_value.openConnection().getInputStream());
//Export File to local Directory
OutputStream stream = new FileOutputStream("path/file_name.png");
/* Write bitmap to file using JPEG or PNG and 80% quality hint for JPEG. */
bitmap.compress(CompressFormat.PNG, 80, stream);
stream.close();
}
I'm trying to save an audio file to send it to whatsapp, but i am unable to save it on external storage. I am not getting where am I making mistakes.
I am using this code:
FileOutputStream outputStream;
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES), "FUNG");
if (!file.mkdirs()) {}
try {
outputStream = new FileOutputStream(file);
outputStream.write(R.raw.badum2);
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri uri = Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES) + "/FUNG/badum2.m4a");
shareIntent.setType("audio/m4a");
shareIntent.setPackage("com.whatsapp");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(shareIntent);
When the file is sent to WhatsApp, it shows error like:
"fail to share, please try again"
I don't see the audio file in directory, so I guess the error is that I am making some mistakes in saving audio files on external storage.
Please help me in solving this.
I see multiple problems:
(1) if (!file.mkdirs()) {} creates a directory at the path of file, later you use that directory to open an output stream, which of course does not work.
Solution:
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES), "FUNG/badum2.m4a"); // assumed target file
if (!file.getParentFile().mkdirs() && !file.getParentFile().isDirectory()) {
// Abort! Directory could not be created!
}
(2) outputStream.write(R.raw.badum2); will write the int value referring
to your resource, not the resource itself.
Solution:
Use InputStream in = ctx.getResources().openRawResource(R.raw.badum2); where ctx is a Context instance (e.g. your Activity) and write its content to the file.
try {
outputStream = new FileOutputStream(file);
try {
InputStream in = ctx.getResources().openRawResource(R.raw.badum2);
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer, 0, buffer.length) >= 0) {
outputStream.write(buffer, 0, read);
}
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Here is I want to make. I want to make an app, for example it has a button that will download a certain video file and put it on the resource(raw) folder. Is it possible?
Short answer : You can not.
You can not, under any circumstance, write/dump a file to the raw/assets folder in runtime.
What you can do is to download the video and store it into Internal Memory (application reserved storage) or External Memory (usually your SDCard))
For example, you can store media files, for instance a Bitmap to your external storage like this.
private void saveAnImageToExternalMemory(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
String fname = "yourimagename.jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
And equally, read an file, in this example an image (which is then loaded to an imageView), from external memory
private void loadImageFromStorage(String path){
try {
File f=new File(path, "profile.jpg");
Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
ImageView img=(ImageView)findViewById(R.id.imgPicker);
img.setImageBitmap(b);
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Edit: Additionally, you can store your data into internal memory
Alternatively you can also save the Bitmap to the internal storage in
case the SD card is not available or for whatever other reasons you
may have. Files saved to the internal storage are only accessible by
the application which saved the files. Neither the user nor other
applications can access those files
public boolean saveImageToInternalStorage(Bitmap image) {
try {
FileOutputStream fos = context.openFileOutput("yourimage.png", Context.MODE_PRIVATE);
// Writing the bitmap to the output stream
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
return true;
} catch (Exception e) {
Log.e("saveToInternalStorage()", e.getMessage());
return false;
}
}
Check this documentation for more information
Regards,
I am trying to use a method to generate a bitmap from Layouts and save the bitmap to a file in the internal memory. However, the getApplicationContext() is not resolved.
Here is the code for the method
private void generateAndSaveBitmap(View layout) {
//Generate bitmap
layout.setDrawingCacheEnabled(true);
layout.buildDrawingCache();
Bitmap imageToSave = layout.getDrawingCache();
//Create a file and path
ContextWrapper cw = new ContextWrapper(getApplicationContext());
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
File fileName = new File(directory, "sharableImage.jpg");
if (fileName.exists())
fileName.delete();
//Compress and save bitmap under the mentioned fileName
FileOutputStream fos = null;
try {
fos = new FileOutputStream(fileName);
imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// return directory.getAbsolutePath();
}
Used some help from StackOverFlow codes to generate this method. Even after reading related queries on getApplicationContext(), I am unable to find the issue. Any help would be really appreciated
EDIT : Forgot to mention, that the method generateAndSaveBitmap(View layout) is defined inside a separate class
Regards
Step #1: Delete ContextWrapper cw = new ContextWrapper(getApplicationContext());, as you do not need it.
Step #2: Replace cw.getDir("imageDir", Context.MODE_PRIVATE); with layout.getContext().getDir("imageDir", Context.MODE_PRIVATE);
Also, please move this disk I/O to a background thread.
Try ,
ContextWrapper cw = new ContextWrapper(getActivity());
incase it's a fragment.
Have you tried:
File dir = getApplicationContext().getDir(Environment.DIRECTORY_PICTURES, Context.MODE_PRIVATE);
Now, from the image processing to the write of the file into the directory everything should be done off thread. Encapsulate it in an AsyncTask when possible and within it move generateAndSaveBitmap() method to it.
I've been working with this PDF library, trying to get the path to where the PDF file resides, but I keep getting an error. What am I missing here?
Checking my Android Device Monitor, i can see my db in that database folder which also reside in the assets folder but i can't find all the pdf files? please where are they? check the image below
Thanks friends, it was my mistake, i just discovered that i need to read the file from assets into file directory before opening it. Is working right now using the code below
`
private void CopyReadAssets(String fileName)
{
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(this.getFilesDir(), fileName);
try
{
in = assetManager.open(fileName);
out = this.openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);
Utility.copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag", e.getMessage());
}
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
File dir_file = new File(file.getAbsolutePath());
//<-- Get FileType
String mimeType = Utility.getFileMineType(dir_file);
intent.setDataAndType(Uri.fromFile(file), mimeType); //"file://" + getFilesDir() + "/abc.pdf"),"application/pdf"
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if(mimeType.equals("application/pdf")){
Log.e(TAG, Uri.fromFile(file).toString()+" -- "+dir_file);
//mPDFView = new StudentPdfViewer();
// mPDFView.display("Symfony.pdf", false);
//handle it as activity
Intent intent1 = new Intent(this, PdfViewer.class);
intent1.putExtra(Config.COURSE_FILE, fileName);
//intent1.putExtra(SqliteDb.COURSE_NAME, listCategory.get(0).getCategory_name());
//intent1.putExtras(mBundle);
startActivity(intent1);
}else{
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, "Unable to load selected Course Material, Please check the Study Studio installation guide to install the required dependency softwares", Toast.LENGTH_LONG).show();
}
}
}
`
There is no "assets folder" on the device, and there is no "path to where the PDF file reside" on the device.
The contents of the assets/ folder(s) in your app's project are stored inside the APK. You can access assets via an AssetManager, and you get one of those by calling getAssets() on any handy Context, such as an Activity.