I have worked out how to fire an e-mail and fill it with information from a database query, but I would like to instead write this to a CSV file so I can use excel to format (maybe attached to an e-mail if this is at all possible).
Below is my code which creates the text to send to an e-mail:
private void exportRedRiskItemsToEmail(){
recipient = email;
subject.append(inspectionRef).append(" - Locators Rack Inspection Report (Red Risk Items)");
message.append("Dear ").append(contactFirstName).append(",\r\n");
message.append("\r\n");
message.append("Following todays inspection, below is a list of locations which are noted as Red Risk:\r\n");
final Cursor areasCursor = (Cursor) rmDbHelper.fetchAllAreasForInspection(inspectionId);
if(areasCursor.moveToFirst()){
do{
areaId = areasCursor.getLong(areasCursor.getColumnIndex(RMDbAdapter.AREA_ID));
areaNumber = RMUtilities.notEmpty(areasCursor.getString(areasCursor.getColumnIndex(RMDbAdapter.AREA_NUMBER)), "number unknown");
areaRef = RMUtilities.notEmpty(areasCursor.getString(areasCursor.getColumnIndex(RMDbAdapter.AREA_REF)), "");
if (areaRef != ""){
areaRef = " (" + areaRef + ")";
}
message.append("______________________________________________________").append("\r\n");
message.append("\r\n");
message.append("Area ").append(areaNumber).append(areaRef).append("\r\n");
message.append("\r\n");
}
while (areasCursor.moveToNext());
}
areasCursor.close();
message.append("______________________________________________________").append("\r\n");
message.append("\r\n");
message.append("Please fully off-load above locations (for uprights, please off-load bays either side). \r\n");
message.append("\r\n");
message.append("We will follow up with our full report and quotation for repairs shortly. \r\n");
message.append("\r\n");
message.append("In the meantime, if you have any queries, please give me a call on 07970 088845. \r\n");
message.append("\r\n");
message.append("Kind regards, \r\n");
message.append("\r\n");
message.append(inspector).append("\r\n");
sendEmail(recipient, subject.toString(), message.toString());
}
Here is the code which fires the e-mail:
private void sendEmail(String recipient, String subject, String message) {
try {
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("plain/text");
emailIntent.setType("message/rfc822");
// emailIntent.setType("high/priority"); //This didn't work - any way to do this though!?
if (recipient != null) emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{recipient});
if (subject != null) emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
if (message != null) emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
startActivity(Intent.createChooser(emailIntent, "Send mail..."));
} catch (ActivityNotFoundException e) {
// cannot send email for some reason
}
}
Any pointers much appreciated.
You may want to look at the OpenCSV library. It is free, open source, and easy to use. It does not support directly dumping from SQLite DBs, but it should be pretty straight forward to write the neccessary code to implement this. OpenCSV does support writing Lists of objects to CSV, so if you can get your data out of the sqlite DB into a List you will be good to go.
Also here is a post on the topic.
OpenCSV will write to a file as well. This file then can be attached to an email, or used however you wish(uploaded to google drive, transfered to computer via usb,etc.)
CSVWriter writer = new CSVWriter(new FileWriter("yourfile.csv"));
// feed in your array (or convert your data to an array)
writer.write(entries);
writer.close();
This is just a snippet and I'm working from memory write now so it may be a bit off. You may also lookup writing files in android. You can either store this on the external memory or in your application memory. If you want to access the file from outside your app you will need to place it in external memory.
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendIntent.putExtra(Intent.EXTRA_SUBJECT,"subject line");
sendIntent.putExtra(Intent.EXTRA_TEXT,"Body of email");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File("yourfile.csv")));
sendIntent.setType("vnd.android.cursor.dir/email");
startActivity(Intent.createChooser(sendIntent,"Email:"));
Related
I'm building an app that allows the user to save the bitmap or share it without saving it. The 2nd functionality doesn't quite work. I understand that the app needs to save the file to the device before sharing it on a social media app so my idea was, immediately after the file was successfully shared, to automatically delete the file from the device. I've build a delete method trying 2 different approaches and neither have worked:
First approach:
public void deleteFile(String path){
File file = new File(path);
try {
file.getCanonicalFile().delete();
} catch (IOException e) {
e.printStackTrace();
}
}
Second approach:
public void deleteFile(String path){
File file = new File(path);
boolean deleted = file.delete();
}
And I'm calling deleteFile(String) from the sharing method:
public void shareMeme(Bitmap bitmap) {
String path = MediaStore.Images.Media.insertImage(Objects.requireNonNull(getContext()).getContentResolver(), bitmap, "Meme", null);
Uri uri = Uri.parse(path);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
share.putExtra(Intent.EXTRA_TEXT, "This is my Meme");
getContext().startActivity(Intent.createChooser(share, "Share Your Meme!"));
deleteFile(path);
}
With respect to your stated problem, insertImage() returns a string representation of a Uri. That Uri is not a file. Calling getPath() on it is pointless, and you cannot delete anything based on that path.
More broadly, if your intention is to delete the content right away:
Do not put it in the MediaStore
Do not share it, as you will be deleting it before the other app has a chance to do anything with it
If you want to share it, but then delete it:
Do not put it in the MediaStore
Delete it the next day, or in a few hours, or something, as you have no good way of knowing when the other app is done with the content
To share an image with another app without using the MediaStore:
Save the image to a file in getCacheDir() (call that on a Context, such as an Activity or Service)
Use FileProvider to make that file available to other apps
Beyond that:
Do not use wildcard MIME types in ACTION_SEND. You are the one who is supplying the content to send. You know the actual MIME type. Use it.
Note that there is no requirement for an ACTION_SEND activity to honor both EXTRA_TEXT and EXTRA_STREAM. Most seem to do so, but that behavior is outside of the ACTION_SEND specification.
Note that insertImage() is deprecated on Android Q.
First, you need to check if your file exists, (maybe you set the wrong path?). Then delete the file
File file = new File(path);
if (file.exists()){
if (file.delete()) {
Toast.makeText(this, "file Deleted :" + path, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "file not Deleted :" + path, Toast.LENGTH_SHORT).show();
}
}
When sharing a file (text file in this case), is it possible to specify an attribute that limits the number of apps to select?
For example, I run an ACTION_SEND by Intent to share a text file through FileProvider interposed. Android then proposes 10 or 12 apps, whereas only one or two manage to exploit the text file: Gmail, to send an email, X-plore or Total Commander to copy it, but not Chomp to send an sms with attachment, nor such or such notepad...
For example we would need an attribute type: "mail" + "storage" and what else!?
My code, to illustrate and that works well on an external file:
File file = new File(Environment.getExternalStorageDirectory() +
File.separator + filepath, filename);
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/*");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {" "});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, »Bla « bla bla);
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,"[" +
file.getName() + "]");
Uri fileUri = FileProvider.getUriForFile(this
, getString(R.string.fileProvAuthorities)
, file);
emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(Intent.createChooser(emailIntent, "To share"));
There's nothing like that. But you could create your own chooser showing only the apps you want.
You can do that easily via Flipboard BottomSheet library
Here is a sample:
First, create a string array includes the package names of apps to be shared with, into your strings.xml file like that:
<string-array name="share_apps">
<item>com.facebook.katana</item>
<item>com.facebook.orca</item>
<item>com.twitter.android</item>
<item>com.whatsapp</item>
<item>com.google.android.apps.messaging</item>
<item>com.google.android.talk</item>
<item>com.google.android.gm</item>
<item>com.google.android.apps.plus</item>
<item>com.pinterest</item>
<item>com.instagram.android</item>
<item>com.android.email</item>
<item>com.microsoft.office.outlook</item>
<item>com.yahoo.mobile.client.android.mail</item>
<item>ru.yandex.mail</item>
</string-array>
You can add or remove whatever you want in the list. Then, you can use the bottomsheet like below
IntentPickerSheetView intentPickerSheet = new IntentPickerSheetView(MainActivity.this, shareIntent, "Share with...", new IntentPickerSheetView.OnIntentPickedListener() {
#Override
public void onIntentPicked(IntentPickerSheetView.ActivityInfo activityInfo) {
bottomSheet.dismissSheet();
startActivity(activityInfo.getConcreteIntent(shareIntent));
}
});
// Filter out built in sharing options such as bluetooth and beam.
intentPickerSheet.setFilter(new IntentPickerSheetView.Filter() {
#Override
public boolean include(IntentPickerSheetView.ActivityInfo info) {
String packageName = info.componentName.getPackageName();
ArrayList<String> apps = new ArrayList<String>(Arrays.asList(getResources().getStringArray(R.array.share_apps)));
return apps.contains(new String(packageName));
}
});
// Sort activities in reverse order for no good reason
intentPickerSheet.setSortMethod(new Comparator<IntentPickerSheetView.ActivityInfo>() {
#Override
public int compare(IntentPickerSheetView.ActivityInfo lhs, IntentPickerSheetView.ActivityInfo rhs) {
return rhs.label.compareTo(lhs.label);
}
});
bottomSheet.showWithSheetView(intentPickerSheet);
Im interested in running some custom analytics on my interactions with contacts on my phone.
Some things I would like to see are:
How many times was this contact called
How long did the conversation last
How many missed calls from this contact
How many answered calls from this contact
What time and date was an sms sent
What was its message content
What time and date was an sms received
What was its message content
If it was mms can i get the picture some how
Ill use a third party api for facial recognition and nudity checks (was it a nude, selfie, meme)
Is there a way to simply export this data into a xml or csv file? (How would I save pictures?)
My goal here is to make an app using some sort of android java sdk. Then using the app, ill upload to my web server and use php to do the analytics.
Where do i look to start getting the information i want to analyze?
Try to look at these links:
PhoneStateListener
TelephonyManager
Read SMS
ContentResolver
To export your pictures from mms use a filestream and a bitmap:
private void GetMmsAttachment(String _id, String _data)
{
Uri partURI = Uri.parse("content://mms/part/" + _id );
String filePath = "/sdcard/photo.jpg";
InputStream is = null;
OutputStream picFile = null;
Bitmap bitmap = null;
try {
is = getContentResolver().openInputStream(partURI);
bitmap = BitmapFactory.decodeStream(is);
picFile = new FileOutputStream(filePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, picFile);
picFile.flush();
picFile.close();
}
catch (Exception e)
{
e.printStackTrace();
//throw new MmsException(e);
}
}
Also for photo Identification I recommend you use IBM Watson,.If the photo has text use Google Tesseract to extract the text.
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'm working on an Android application that should allow the users to share their content via Gmail. I'm using android version 2.2(Froyo).
The problem is that I can't find any working solution for this, I tried almost everything ,but with no luck.
this is the code I'm using:
Intent sharingIntent = new Intent(Intent.ACTION_SEND);;
sharingIntent.setType("application/zip");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
getString(R.string.share_subject));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, getString(R.string.share_body));
String zipFile = FileProvider.URI_AUTHORITY + File.separator + mItemSelected.getLibraryName() + File.separator + mItemSelected.getZipFileName();
sharingIntent.putExtra(Intent.EXTRA_STREAM, android.net.Uri.parse(zipFile));
startActivity(Intent.createChooser(sharingIntent, (getString(R.string.share_chooser))));
}
The problem in this case is that the Gmail app, for no obvious reason, is replacing the mime type of the file, and show the file as text/html, and then my application is not shown in the application list that can deal with this kind of file. Another restriction is that I don't want to use text/html in my intent filter, because I want it to be focused as much as possible, and if it were possible I would define my own mime type...
I did a little research and found this question, but with no answers...
More mime types I tried:
application/x-compressed, application/x-zip-compressed
multipart/x-zip and application/octet-stream
Is there any solution for this problem ??
Thanks.
after a lot of trouble, I discovered that Gmail, launched via Intent, does not like attachments whose prefix is .zip.
So, I succeeded in sending the attachments after renaming it ".vip".
Here is a piece of code (outFile is a zipped file renamed as ".vip"):
enter
private void sendMail(File outFile) {
Uri uriToZip = Uri.fromFile(outFile);
String sendText = "Dear friend,\n\n...";
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
new String[] { "checcodotti#gmail.com" });
sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, sendText);
sendIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Log of the test " + expFilename);
// sendIntent.setType("image/jpeg");
// sendIntent.setType("message/rfc822");
sendIntent.setType("*/*");
sendIntent.putExtra(android.content.Intent.EXTRA_STREAM, uriToZip);
startActivity(Intent.createChooser(sendIntent, "Send Attachment !:"));
}
Please let me know if it helps.
Regards
FD
I improve my previous answer for the part concerning "zipping". Now the are no problems with .zip attachments sent via GMail or whatever. Try this:
{
int lung;
FileInputStream in;
FileOutputStream out;
byte[] buffer = new byte[DIM_BUFFER];
// compress the file to send
String inPath = ctx.getApplicationContext().getFilesDir().getAbsolutePath();
outFile = new File(outPath,TestEdit.ZIPNAME);
// outFile = new File(outPath,filename + ".vip");
in = new FileInputStream(inFile);
ZipEntry entry = new ZipEntry(filename + ".csv");
try{
out = new FileOutputStream(outFile);
// GZIPOutputStream zos;
ZipOutputStream zos;
zos = new ZipOutputStream(new BufferedOutputStream(out) );
zos.putNextEntry(entry);
try {
while ((lung=in.read(buffer)) > 0) {
Log.v(TAG, "Lunghezza di in=" + lung + ". Lungh di buffer=" + buffer.length );
if (buffer.length == lung) {
zos.write(buffer);
} else {
// Gestione del caso in cui il buffer non sia pieno
for (int b = 0; b < lung; b++) {
zos.write(buffer[b]);
}
}
}
} finally {
zos.closeEntry();
zos.close();
in.close();
out.close();
}
}
}