I write a file into the SD. I Know the file is OK because using ASTRO app or Gmail app or Yahoo app, I can see it and I can also attach it from them but when I try to attach the file from my app the thing is quite different. When I choose gmail or yahoo app they can't read the file. But if I choose the default app the email is sent correctly with the file attached.
Here is my code. THANKS!!
Inside AndroidManifest
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
Where I make the file
File ruta_sd = Environment.getExternalStorageDirectory();
File f;
// Creo la carpeta;
File folder = new File(ruta_sd.getAbsolutePath() + "/Torno");
folder.mkdirs();
f = new File(ruta_sd.getAbsolutePath() + "/Torno/","Torno.xml");
// Just trying
f.canRead();
OutputStreamWriter fout = new OutputStreamWriter(new FileOutputStream(f));
fout.write(c); <-- c is a String in xml format
// Just trying
fout.flush();
fout.close();
Now, where I try to attach it
String ruta = Environment.getExternalStorageDirectory().getPath() + "/Torno/Torno.xml";
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType(getMimeType(ruta));
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(ruta));
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "el tema");
sendIntent.putExtra(Intent.EXTRA_TEXT, "el cuerpo del mensaje");
// Just trying
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(sendIntent, "Title:"));`
Presumably there is something wrong with your path. Change:
String ruta = Environment.getExternalStorageDirectory().getPath() + "/Torno/Torno.xml";
...
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(ruta));
to:
File ruta = new File(Environment.getExternalStorageDirectory(), "/Torno/Torno.xml");
...
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(ruta));
and see if that helps (along with getting rid of FLAG_GRANT_READ_URI_PERMISSION, and perhaps trying sync()).
At the end, It worked!!! I don't really know what was happening. I was trying with my phone as emulator with eclipse without installing the app and the e.getMessage() of the exception was: "/storage/sdcard/Torno/Torno.xml: open failed: ENOENT (No such file or directory)"
Finally, I thought to install the app and it worked!! This is the current code:
btnAceptar.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String contenido="";
File fichero = null;
if (rdXML.isChecked()){
contenido = creaFichero(1,Integer.parseInt("" + txtAno.getText()),Integer.parseInt("" + txtMes.getText()));
fichero = grabarFichero(contenido, "Torno.xml");
}
else{
contenido = creaFichero(2,Integer.parseInt("" + txtAno.getText()),Integer.parseInt("" + txtMes.getText()));
fichero = grabarFichero(contenido, "Torno.txt");
}
if (fichero==null){
Toast toast = Toast.makeText(getApplicationContext(),"No hay datos para ese mes !!", Toast.LENGTH_LONG);
toast.show();
}
else{
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType(getMimeType(fichero.getAbsolutePath()));
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(fichero));
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "el tema");
sendIntent.putExtra(Intent.EXTRA_TEXT, "el cuerpo del mensaje");
startActivity(Intent.createChooser(sendIntent, "Title:"));
}
}
});
public static String getMimeType(String url){
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
private File grabarFichero(String c,String n){
File file = null;
try {
// Creo la carpeta;
File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Torno");
folder.mkdirs();
file = new File(Environment.getExternalStorageDirectory() + "/Torno", n);
OutputStreamWriter outw = new OutputStreamWriter(new FileOutputStream(file));
outw.write(c);
outw.close();
}
catch (Exception e) {}
return file;
}
THANKS!!!
Related
Hello evrybody i'm tryng to share an image on messenger but i don't know why my code doesen't work, I've followed the official guide, https://developers.facebook.com/docs/messenger/android
someone can told me why doese'nt work?
public void sendMessage(){
Bitmap adv= takePic(HomeActivity.livelloCurrent.getNumeroLivello());
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
adv.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
File f = new File(Environment.getExternalStorageDirectory()+ File.separator + "temporary_file.jpg");
try {
f.createNewFile();
new FileOutputStream(f).write(bytes.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
String mimeType = "image/jpeg";
Intent sendIntent = new Intent();
sendIntent.setType(mimeType);
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM,Uri.parse(Environment.getExternalStorageDirectory() + File.separator + "temporary_file.jpg"));
sendIntent.putExtra(Intent.EXTRA_TEXT, "<---MY TEXT--->.");
sendIntent.setPackage("com.facebook.orca");
try {
startActivity(sendIntent);
}
catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(getApplicationContext(),"Please Install Facebook Messenger", Toast.LENGTH_LONG).show();
}
/** //withSDK-->// ShareToMessengerParams shareToMessengerParams = ShareToMessengerParams.newBuilder(ContentUri, mimeType).build();
MessengerUtils.shareToMessenger(this, REQUEST_CODE_SHARE_TO_MESSENGER, shareToMessengerParams);**/
}
Im sure that the file creation work cause i have tested it . in testing I get the following error from messenger "Sorry, Messenger was not able to process the file".
how can i solve ?
Replace:
Uri.parse(Environment.getExternalStorageDirectory() + File.separator + "temporary_file.jpg")
with:
Uri.fromFile(f)
I'm developing an app in which I'm sending a .txt file from one end by attaching it with gmail. Everytime this file is sent, its name is data.txt. When this file is downloaded at the other end, on the first download its name is the same, i.e. data.txt. However, when another file is sent with the same name, the name of the file at the receiveing end becomes data-1.txt, data-2.txt etc. And because of this, I'm not able to read the proper file. Please could someone give me some suggestions to solve this problem? The sending and receiving code is given below: SEND
bSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String fileName = "data";
String toWrite = enterText.getText().toString();
FileOutputStream fos;
try {
String path = Environment.getExternalStorageDirectory().toString();
Log.v("path", path);
File myFile = new File("" + path + "/" + fileName + ".txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(toWrite);
Log.v("file written", toWrite);
myOutWriter.close();
fOut.close();
Uri u1 = null;
u1 = Uri.fromFile(myFile);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "MPPT Configuration Data");
sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
sendIntent.setType("text/html");
startActivity(sendIntent);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
READ:
bRead.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String fileName = "data";
StringBuffer stringBuffer = new StringBuffer();
String aDataRow = "";
String aBuffer = "";
try {
File myFile = new File("/storage/sdcard0/download/" + fileName + ".txt");
FileInputStream fIn = new FileInputStream(myFile);
BufferedReader myReader = new BufferedReader(
new InputStreamReader(fIn));
while ((aDataRow = myReader.readLine()) != null) {
aBuffer += aDataRow + "\n";
}
myReader.close();
Log.v("read data", "" + aBuffer);
tvData.setText(aBuffer);
}catch (IOException e2) {
e2.printStackTrace();
}
}
});
I found a possible solution. I can link the file manager (external app) from where the user can pick out whichever file he wants to be read.
Thanks #greenapps fir the idea of displaying a list of files.
You can get all the file by using regex ,then process the file by following way:
1.if only one file found,read it;
2.if more than one file found, compare and read the file which last number is biggest
but this solution still has one problem,if has file data.txt and data-3.txt ,the file we want to read may become data-2.txt,but what we really read is data-3.txt.
Or,maybe you can get the file you want by judging file established time.
In My Application I download PDF file to internal storage. after this I want to send mail with the file. I see the file is dowloaded in internal memory
com.my.app -> files-> pdffile.pdf
and it has permissions -rw-------
when I attach to mail the file and send gmail says: could't send attachment. But why ?? I have permission
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
this is code for dowloading file. it runs in async task
public static boolean saveFile(String fileName, Context context){
String fileDirectory = context.getFilesDir().getAbsolutePath()
+ "//"+fileName;
String urlServ = Constants.serverUrl+ "upload/forms/"+fileName;
urlServ = urlServ.replace(" ", "%20");
urlServ = urlServ.replace("\n", "%0d");
urlServ = urlServ.replace("\"", "%22");
int count;
URI fUri = URI.create("file://" + fileDirectory);
File f = new File(fileDirectory);
if (f.exists()){
f.delete();
}
try {
URL url = new URL(urlServ);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(fileDirectory);
//OutputStream output = context.openFileOutput(fileDirectory, Context.MODE_PRIVATE);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
return false;
}
return true;
}
And this is code for sending mail :
public static void sendMail(Context context, String filename) {
String fileDirectory = context.getFilesDir().getAbsolutePath()
+ "/"+filename;
File f = new File(fileDirectory);
Uri URI =Uri.fromFile(f);
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL , new String[]{"mytestmail#gmail.com"});
i.putExtra(Intent.EXTRA_SUBJECT, "subject of email");
i.putExtra(Intent.EXTRA_STREAM, URI);
i.putExtra(Intent.EXTRA_TEXT , "body of email");
try {
context.startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(context, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
}
What is wrong ? it sands mail only with subject and text... maybe there is some permissions issue. How can I donwload file and give it full permissions
EDIT:
It is permission issue, because when I send file with different permission from the same directory, mail with attachment is being sent. -rw-rw-rw- with this permission
How Can i donwload file and set -rw-rw-rw- permission to it ???
I have solved the problem, if anyone faces the same issue. When opening OutputStream like this
it gives new file permission -rw-rw-rw. and other application(Gmail in this case) can use it.
OutputStream output = context.openFileOutput( fileName, Context.MODE_WORLD_READABLE);
The problem here is that although your app has permissions to read the file, the email application doesn't have permission to read the file. Since Jelly Bean, StrictMode has produced a warning when you try to share a File URI outside your application because this kind of problem can occur where the app you are sharing a file with does not have permission to access the file. It is advised to use a content:// URI when sharing files between apps instead of a file:// URI.
I'd suggest using the FileProvider class, which provides a relatively simple way to share your files using a content:// URI.
I'm trying to share a downloaded bitmap via Android's ShareActionProvider, and I'm having an issue actually passing the bitmap to appropriate apps (such as Messenger, Google+, Gmail). When I pass the intent with the uri, nothing happens (image isn't populated in the 3rd party app).
Here is my Intent:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
writeToDirectory(bitmap, "cached-image.png"); // write bitmap to file system in order to share
intent.putExtra(Intent.EXTRA_STREAM, getFileUri("cached-image.png"))
mShareActionProvider.setShareIntent(intent);
I'm currently saving the bitmap to file using the following:
public String writeToDirectory(Bitmap bitmap, String filename) {
assert context != null;
assert bitmap != null;
assert filename != null;
// Ensure directory exists and create if not
String path = Environment.getExternalStorageDirectory() + File.separator + "myApp";
File f = new File(path);
boolean dirExists = f.isDirectory();
if (!f.isDirectory() && !f.exists()) {
dirExists = f.mkdirs();
}
if (dirExists) {
File file = new File(sharedPrivateExternalPath, filename);
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
} catch (IOException ex) {
e(TAG, "Write failed!");
e(TAG, ex.getMessage());
ex.printStackTrace();
}
return file.toString();
} else {
return "";
}
}
and I'm retrieving the Uri with this method
public Uri getFileUri(String filename) {
assert context != null;
assert filename != null;
String path = Environment.getExternalStorageDirectory() + File.separator + "myApp";
File file = new File(path, filename);
return Uri.fromFile(file);
}
I've checked that the file gets written to the appropriate place (Uri is file:///storage/emulated/0/myApp/cached-image.png) and was able to view the image there (did an adb pull from the device), though the image doesn't get passed. I don't see any errors in the log (no FileNotFoundException or anything of the sort). Is this a file permission issue? Am I not able to share to a "non-public" location?
If I change getExternalStorageDirectory() + File.separator + "myApp"; to plain getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) it works fine... but it's bothering me it doesn't work the other way :).
Any help would be great!
Turns out it had to do with code I didn't post (surprise, surprise). I was attempting to set the shareIntent in the setOnShareTargetSelectedListener... which apparently you can't do.
My problem was with this code snippet
mShareActionProvider = (ShareActionProvider)
MenuItemCompat.getActionProvider(shareItem);
mShareActionProvider.setOnShareTargetSelectedListener(new ShareActionProvider.OnShareTargetSelectedListener() {
#Override
public boolean onShareTargetSelected(ShareActionProvider shareActionProvider, Intent intent) {
String urlKey = mImageUrlList.get(mImageGallery.getCurrentItem()) + "\n";
// This is the problem line
mShareActionProvider.setShareIntent(getImageIntent(app.getImageCache().get(urlKey)));
return false;
}
})
I am using following code to download and read a PDF file from internal storage on device.
I am able to download the files successfully to the directory:
data/data/packagename/app_books/file.pdf
But I am unable to read the file using a PDF reader application like Adobe Reader.
Code to download file
//Creating an internal dir;
File mydir = getApplicationContext().getDir("books", Context.MODE_WORLD_READABLE);
try {
File file = new File(mydir, outputFileName);
URL downloadUrl = new URL(url);
URLConnection ucon = downloadUrl.openConnection();
ucon.connect();
InputStream is = ucon.getInputStream();
FileOutputStream fos = new FileOutputStream(file);
byte data[] = new byte[1024];
int current = 0;
while ((current = is.read(data)) != -1) {
fos.write(data, 0, current);
}
is.close();
fos.flush();
fos.close();
isFileDownloaded=true;
} catch (IOException e) {
e.printStackTrace();
isFileDownloaded = false;
System.out.println(outputFileName + " not downloaded");
}
if (isFileDownloaded)
System.out.println(outputFileName + " downloaded");
return isFileDownloaded;
Code to read the file
PackageManager packageManager = getPackageManager();
Intent testIntent = new Intent(Intent.ACTION_VIEW);
testIntent.setType("application/pdf");
List list = packageManager.queryIntentActivities(testIntent,
PackageManager.MATCH_DEFAULT_ONLY);
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
File fileToRead = new File(
"/data/data/com.example.filedownloader/app_books/Book.pdf");
Uri uri = Uri.fromFile(fileToRead.getAbsoluteFile());
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
} catch (Exception ex) {
Log.i(getClass().toString(), ex.toString());
Toast.makeText(MainActivity.this,
"Cannot open your selected file, try again later",
Toast.LENGTH_SHORT).show();
}
All works fine but the reader app says "File Path is not valid".
Your path is only valid for your app. Place the file in a place where other apps can 'see' it. Use GetExternalFilesDir() or getExternalStorageDirectory().
Note about files which are created inside the directory created by Context.getDir(String name, int mode) that they will only be accessible by your own application; you can only set the mode of the entire directory, not of individual files.
So you can use Context.openFileOutput(String name, int mode). I'm re-using your code for an example:
try {
// Now we use Context.MODE_WORLD_READABLE for this file
FileOutputStream fos = openFileOutput(outputFileName,
Context.MODE_WORLD_READABLE);
// Download data and store it to `fos`
// ...
You might want to take a look at this guide: Using the Internal Storage.
If you would like to keep the file app specific, you can use PdfRenderer available for Lollipop and above builds. There are great tutorials on google and youtube that work well. The method you are using is a secure way to store a PDF file that is only readable from inside the app ONLY. No outside application like Adobe PDF Reader will be able to even see the file.It took me a lot of seaching but I found a solution to my specific usage by using this site and especially youtube.
How to download PDF file from asset folder to storage by making folder
make sure you have storage permission are given like marshmallow device support etc then follow these steps
private void CopyReadAssets()
{
AssetManager assetManager = getContext().getAssets();
FileInputStream in = null;
FileOutputStream out = null;
File sdcard = Environment.getExternalStorageDirectory();
File dir = new File(Environment.getExternalStorageDirectory()+File.separator+ "A_level");
File dir2;
if (dir.exists() && dir.isDirectory()){
Log.e("tag out", ""+ dir);
}else {
dir.mkdir();
Log.e("tag out", "not exist");
}
File file = new File(dir, mTitle+".pdf");
try
{
Log.e("tag out", ""+ file);
out = new FileOutputStream(file);
in = new FileInputStream (new File(mPath));
Log.e("tag In", ""+ in);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag out", ""+ out);
Log.e("tag In", ""+ in);
Log.e("tag", e.getMessage());
Log.e("tag", ""+file);
Log.i("tag",""+sdcard.getAbsolutePath() + "A_level");
}
}
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);
}
}