Android - File provider - Send file via email - android

I am currently looking for a way to save a file in the internal memory of my device, and then to send it by mail. For this, I use FileProvider
So on the Android Manifest, I add those lines in my manifest :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="exploration.syte.fr.sendbymail4.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/paths" />
</provider>
And on res/xml path I added this file path : paths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="files/"/>
</paths>
Here is the code I use to create my file - a really simple text file that contains the word "test".
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String textToWrite = "test";
try {
File path = this.getFilesDir();
File file = new File(path, "myfile.txt");
String chemin = file.getAbsolutePath().toString();
Log.i("MainActivity", chemin);
Toast.makeText(this, chemin, Toast.LENGTH_LONG).show();
FileOutputStream fos = new FileOutputStream(file);
fos.write(textToWrite.getBytes());
fos.close();
//Toast.makeText(this, "File correctly saved", Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.d("Main", "Exception", e);
}
try {
sendFile(this);
} catch (Exception e) {
Log.d("Main", "Exception", e);
}
}
And the code I use to send the file via e-mail
public static void sendFile(Context context){
Intent intent=new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
String directory=(String.valueOf(context.getFilesDir())/*+File.separator+"directory"*/);
File file=new File(directory+File.separator+"myfile.txt");
Uri uri = FileProvider.getUriForFile(context, "exploration.syte.fr.sendbymail4.fileprovider", file);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
}
**The problems that i am currently encoutering are : **
My file is not save in the correct directory : it is save on /data/user/0/exploration.syte.fr.sendbymail4/files/myfile.txt
And I want my file to be save on : /data/data/exploration.syte.fr.sendbymail4/files/myfile.txt
How can I set the path were the file is save correctly ?
Thanks in advance !

I will save the image
public static String saveImage(Context context, Bitmap finalBitmap) {
String root = context.getFilesDir().getAbsolutePath();
// String root = context.getCacheDir().getAbsolutePath();
File myDir = new File(root + subFolder);
if (!myDir.exists()) {
myDir.mkdirs();
}
File file = new File(myDir, dateFilenameFormat.format(new Date()) + ".jpg");
try {
FileOutputStream out = new FileOutputStream(file);
downScale(finalBitmap).compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
return file.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
file_provider_paths.xml
<paths>
<cache-path name="cache" path="/" />
<files-path name="files" path="/" />
</paths>
And send (work for getFilesDir or getFilesDir from "cache" or "files" dirs)
public static void sendEmail(String attachmentFile, String message, Context context) {
try {
String email = "myname#gmail.com";
String subject = "subject";
final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{email});
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
intent.setType("image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// generate URI, I defined authority as the application ID in the Manifest, the last param is file I want to open
File file = new File(attachmentFile);
Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, file);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.putExtra(android.content.Intent.EXTRA_TEXT, message);
context.startActivity(Intent.createChooser(intent, "Sending email..."));
/*
PackageManager pm = context.getPackageManager();
if (intent.resolveActivity(pm) != null) {
context.startActivity(Intent.createChooser(intent, "Sending email..."));
}
*/
} catch (Throwable t) {
Log.d(TAG, t.getLocalizedMessage());
}
}

Related

Not able to download files using download manager

I'm using download manager for downloading files but when I tried to download file using android pie devices it doesn't work.
Can some one tell me what is the alternative for this.
I have also tried adding network config file in the manifest file which was one of the solution i saw when i tried to solve the issue.
For Android 8 and above you have to code like below
Create a folder under res- xml and create a file named -provider_paths
Add this code to provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/YOUR_PACKAGE_NAME/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>
Add below code in Manifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="YOUR_PACKAGE_NAME.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
Create a Async Task to download file from Server
private class DownloadFile extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
downloadDialog = new ProgressDialog(context);
downloadDialog.setCancelable(false);
downloadDialog.setMessage(context.getString(R.string.please_wait));
downloadDialog.show();
}
#Override
protected Void doInBackground(String... strings) {
String fileUrl = strings[0];
String fileName = strings[1];
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File folder = new File(extStorageDirectory, context.getString(R.string.directory));
folder.mkdir();
pdfFile = new File(folder, fileName);
try {
pdfFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
FileDownloader.downloadFile(fileUrl, pdfFile);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
downloadDialog.dismiss();
showMessageWithAction(context.getString(R.string.file_downloaded), pdfFile);
}
}
Excute above AsycTask by new DownloadFile().execute("FILE_URL", "FILE_NAME");
To view file add below code
private void browseFile(File fileName) {
try {
MimeTypeMap mime = MimeTypeMap.getSingleton();
String ext = fileName.getName().substring(fileName.getName().lastIndexOf(".") + 1);
String type = mime.getMimeTypeFromExtension(ext);
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//change file provider name here
Uri contentUri = FileProvider.getUriForFile(Perspective.this, "YOUR_PACKAGE_NAME.fileProvider", fileName);
intent.setDataAndType(contentUri, type);
} else {
intent.setDataAndType(Uri.fromFile(fileName), type);
}
startActivity(intent);
} catch (ActivityNotFoundException anfe) {
Toast.makeText(Perspective.this, "No activity found to open this attachment.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Final changes, add this class in your project
public class FileDownloader {
private static final int MEGABYTE = 1024 * 1024;
public static void downloadFile(String fileUrl, File directory){
try {
URL url = new URL(fileUrl);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
//urlConnection.setRequestMethod("GET");
//urlConnection.setDoOutput(true);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(directory);
int totalSize = urlConnection.getContentLength();
byte[] buffer = new byte[MEGABYTE];
int bufferLength = 0;
while((bufferLength = inputStream.read(buffer))>0 ){
fileOutputStream.write(buffer, 0, bufferLength);
}
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Hope this will help you.

how to email a file generated from an app in android?

I'm developing an android app in which i'll be generating an pdf file which i want to sent as an email. Following is the code for generating pdf file:
public void createPDF(View view) {
Document doc = new Document();
String outPath = Environment.getExternalStorageDirectory()+"/mypdf.pdf";
try {
PdfWriter.getInstance(doc,new FileOutputStream(outPath));
doc.open();
doc.add(new Paragraph(edttxt1.getText().toString()));
doc.add(new Paragraph(txt.getText().toString()));
doc.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Help me to email this file by clicking a button.
you can see more details here: How to send an email with a file attachment in Android
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"email#example.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Your subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "body text");
File root = Environment.getExternalStorageDirectory();
String pathToMyAttachedFile = "/mypdf.pdf";
File file = new File(root, pathToMyAttachedFile);
if (!file.exists() || !file.canRead()) {
return;
}
Uri uri = Uri.fromFile(file);
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailIntent, "Pick an Email provider"));

Opening PDF from external URL says "Open File: No apps can perform this action"

I am trying to open PDF files from external URL. The code is the next:
private void cargaPdf(Uri url){
//File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ filename);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(url,"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open File");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
// Instruct the user to install a PDF reader here, or something
}
}
I have installed adobe and google PDF viewer but when i push the buttom that calls "cargaPdf(Uri url)" function with this url(as you can see is a pdf file):
Uri.parse(https://dl.dropboxusercontent.com/s/oulzgpgnq2ca1ly/KorfbalSpa.pdf?dl=0);
It appears in the screen in spanish "Open File Ninguna aplicacion puede realizar esta accion" or english "Open file No apps can perform this action". What happen?
Edit 1: Ok, now i know that i have to download the file to see it, so, i did this code in the activity:
public void cargaDescripcion(View view){
Log.d("CargaDescripcion", "Antes del directorio");
String extStorageDirectory = Environment.getExternalStorageDirectory()
.toString();
File folder = new File(extStorageDirectory, "Mypdf");
folder.mkdir();
File file = new File(folder, "Read.pdf");
try {
file.createNewFile();
Log.d("CargaDescripcion", "File creado");
} catch (IOException e1) {
e1.printStackTrace();
}
Downloader.DownloadFile(deporte.getUrlDescEs(), file);
Log.d("CargaDescripcion", "Despues de descargarlo");
showPdf();
//folder.delete();
}
public void showPdf()
{
Log.d("showPdf", "Entramos en show pdf");
File file = new File(Environment.getExternalStorageDirectory()+"/Mypdf/Read.pdf");
PackageManager packageManager = getPackageManager();
Intent testIntent = new Intent(Intent.ACTION_VIEW);
testIntent.setType("application/pdf");
List list = packageManager.queryIntentActivities(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(file);
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
//file.delete();
}
And this class for download the pdf:
public class Downloader {
public static void DownloadFile(String fileURL, File directory) {
try {
FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I got it from here Opening pdf file from server using android intent
Edit 2: Now this is the code which download and shows the file:
public void cargaDescripcion(View view){
download(deporte.getUrlDescEs());
showPdf();
//folder.delete();
}
public void download(String url)
{
new DownloadFile().execute(url, "read.pdf");
}
public void showPdf()
{
File pdfFile = new File(Environment.getExternalStorageDirectory() + "/Mypdf/" + "read.pdf"); // -> filename = maven.pdf
Uri path = Uri.fromFile(pdfFile);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try{
startActivity(pdfIntent);
}catch(ActivityNotFoundException e){
Toast.makeText(SelectedSportActivity.this, "No Application available to view PDF", Toast.LENGTH_SHORT).show();
}
}
private class DownloadFile extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... strings) {
String fileUrl = strings[0]; // -> url del archivo
String fileName = strings[1]; // -> nombre del archivo.pdf
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File folder = new File(extStorageDirectory, "Mypdf");
folder.mkdir();
File pdfFile = new File(folder, fileName);
try{
pdfFile.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
Downloader.downloadFile(fileUrl, pdfFile);
return null;
}
}
However, the file system is not created by app and file is not downloaded before the app arrives to the next point, that it is "show". So, the file does not exists when the app looks for it.
Edit 3: to SOLVE the show problem i used onPostExecute of asynctask method:
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
showPdf();
}
Use this code, this works for me for local file.
resumePdfFile is file path, where your file is saved.
private void openPDF(String resumePdfFile) {
//file should contain path of pdf file
Uri path = Uri.fromFile(resumePdfFile);
Log.e("create pdf uri path==>", "" + path);
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(),
"There is no any PDF Viewer",
Toast.LENGTH_SHORT).show();
finish();
}
}
You can view or download the pdf files by two ways i.e by opening it in device default browser or in the webview by embedding it in your app.
To open the pdf in browser,
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(pdf_url));
startActivity(browserIntent);
To open in webview,
Webview webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(pdf_url);

Attachments can not be sent out through email

I am trying to send an email with attachment from my android app. But the email somehow goes out without the attachment, even though the file exists. In the email sending view, it shows the attachment (with file size even), but after sending, on the receiver side, there is no attachment. Any idea why?
private void copyFileToExternal() throws IOException {
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "data/com.dw.inspectionhelperNSTC/databases/Inspection.db";
String backupDBPath = "Inspection_backup.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB)
.getChannel();
FileChannel dst = new FileOutputStream(backupDB)
.getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Toast.makeText(getBaseContext(), "testing", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getBaseContext(), "not exist", Toast.LENGTH_LONG).show();
System.out.println("currentDB does not exists");
}
} else {
Toast.makeText(MainActivity.this,
"NO SDcard so unable to send the database backup",
Toast.LENGTH_SHORT).show();
System.out.println("sdcard cant write");
}
} catch (Exception e) {
Toast.makeText(getBaseContext(), "error", Toast.LENGTH_LONG).show();
System.out.println("exception" + e.getLocalizedMessage());
}
}
private void sendEmail(String email) {
ArrayList<Uri> uris = new ArrayList<Uri>();
// Adding the inspection DB;
File file = new File(Environment.getExternalStorageDirectory(),
"Inspection_backup.db");
Uri path = Uri.fromFile(file);
uris.add(path);
// Adding the stacttrack file with uncaught expection
File file2 = new File(Environment.getExternalStorageDirectory(),
Constant.STACKTRACE_FILE);
Uri path2 = Uri.fromFile(file2);
uris.add(path2);
Intent intent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT,
"inspection database");
String to[] = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT,
"sending inspection database for reporting");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
startActivityForResult(Intent.createChooser(intent, "Send mail..."),
1222);
}
public void sendMailWithIntent(String emailTo,
String subject, String emailText, List<String> filePaths) {
try {
//need to "send multiple" to get more than one attachment
final Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
emailIntent.setType("text/plain");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
Util.extractEmails(emailTo));
// emailIntent.putExtra(android.content.Intent.EXTRA_CC,
// new String[]{emailCC});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, emailText);
ArrayList<Uri> uris = new ArrayList<Uri>();
//has to be an ArrayList
if (filePaths != null) {
//convert from paths to Android friendly Parcelable Uri's
for (String file : filePaths) {
File fileIn = new File(file);
Uri u = Uri.fromFile(fileIn);
uris.add(u);
}
}
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
Intent chooser = Intent.createChooser(emailIntent, "Send mail...");
activity.startActivityForResult(chooser, 1);
} catch (Exception e) {
new ShowToast(context, e.getMessage());
}
}
Call it like
List<String> list = new ArrayList<>();
list.add(TO_ATTACH_ONE);
list.add(TO_ATTACH_TWO);
sendMailTest.sendMailWithIntent(toAddresses, subject, body, list);
private void sendEmail(String filename)
{
String filePath=Environment.getExternalStorageDirectory().toString()+ File.separator+ folderName +File.separator+ filename;
File file = new File(filePath);
Intent i = new Intent(Intent.ACTION_SEND);
i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
i.setType("*/*");
i.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
i.putExtra(Intent.EXTRA_TEXT , "Body");
try {
startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(getApplicationContext(), "No Email Found", 5000);
}
}
I hope it will help you out.

Parent Directory is not Writable Error Android Emulator

Getting "Parent directory of file is not writable" when trying to create a temp file. I am using Eclipse and the emulator. I am using the permission in my Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Here is the code:
#SuppressWarnings("static-access")
public void sendEmail() {
Calendar today = new GregorianCalendar();
Log.d(TAG, "Path:" + Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/GPSTracking/" + MakeTextDate(today) + ".csv");
File tempFile = null;
try {
tempFile.createTempFile(MakeTextDate(today), ".csv");
FileWriter out = FormatEmail(tempFile);
}
catch (IOException e) {
// error
Log.d(TAG, "create temp file:" + e.toString());
}
try {
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
"Trip report");
emailIntent
.putExtra(Intent.EXTRA_TEXT, "Here is your Trips Report");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
emailIntent.setType("plain/text");
startActivity(Intent.createChooser(emailIntent, "Send email..."));
} catch (Exception e) {
e.printStackTrace();
}
}
You're trying to create file in root directory of storage, not sd-card
tempFile.createTempFile(MakeTextDate(today), ".csv");
Create file as you writing log with full path to external storage.

Categories

Resources