Added record audio / take photo

pull/156/head
M66B 6 years ago
parent e56629689c
commit 5780253a14

@ -22,6 +22,9 @@
<uses-feature <uses-feature
android:name="android.software.webview" android:name="android.software.webview"
android:required="false" /> android:required="false" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<application <application
android:name=".ApplicationEx" android:name=".ApplicationEx"

@ -46,7 +46,9 @@ public class ActivityCompose extends ActivityBilling implements FragmentManager.
static final int REQUEST_CONTACT_BCC = 3; static final int REQUEST_CONTACT_BCC = 3;
static final int REQUEST_IMAGE = 4; static final int REQUEST_IMAGE = 4;
static final int REQUEST_ATTACHMENT = 5; static final int REQUEST_ATTACHMENT = 5;
static final int REQUEST_ENCRYPT = 6; static final int REQUEST_TAKE_PHOTO = 6;
static final int REQUEST_RECORD_AUDIO = 7;
static final int REQUEST_ENCRYPT = 8;
static final int PI_REPLY = 1; static final int PI_REPLY = 1;

@ -51,6 +51,7 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.provider.OpenableColumns; import android.provider.OpenableColumns;
import android.text.Editable; import android.text.Editable;
import android.text.Html; import android.text.Html;
@ -94,6 +95,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.Group; import androidx.constraintlayout.widget.Group;
import androidx.core.content.FileProvider;
import androidx.cursoradapter.widget.SimpleCursorAdapter; import androidx.cursoradapter.widget.SimpleCursorAdapter;
import androidx.exifinterface.media.ExifInterface; import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
@ -185,17 +187,19 @@ public class FragmentCompose extends FragmentBase {
private boolean pro; private boolean pro;
private boolean prefix_once = false;
private boolean monospaced = false;
private boolean style = true;
private boolean plain_only = false;
private boolean encrypt = false;
private long working = -1; private long working = -1;
private State state = State.NONE; private State state = State.NONE;
private boolean show_images = false; private boolean show_images = false;
private boolean autosave = false; private boolean autosave = false;
private boolean busy = false; private boolean busy = false;
private Uri photoURI = null;
private boolean prefix_once = false;
private boolean monospaced = false;
private boolean style = true;
private boolean plain_only = false;
private boolean encrypt = false;
private OpenPgpServiceConnection pgpService; private OpenPgpServiceConnection pgpService;
private long[] pgpKeyIds; private long[] pgpKeyIds;
private long pgpSignKeyId; private long pgpSignKeyId;
@ -335,13 +339,23 @@ public class FragmentCompose extends FragmentBase {
etBody.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT); etBody.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT);
tvReference.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT); tvReference.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT);
PackageManager pm = getContext().getPackageManager();
Intent take_photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent record_audio = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
edit_bar.getMenu().findItem(R.id.menu_take_photo).setVisible(take_photo.resolveActivity(pm) != null);
edit_bar.getMenu().findItem(R.id.menu_record_audio).setVisible(record_audio.resolveActivity(pm) != null);
edit_bar.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { edit_bar.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override @Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) { public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int action = item.getItemId(); int action = item.getItemId();
switch (action) { switch (action) {
case R.id.menu_link: case R.id.menu_record_audio:
onActionLink(); onActionRecordAudio();
return true;
case R.id.menu_take_photo:
onActionTakePhoto();
return true; return true;
case R.id.menu_image: case R.id.menu_image:
onActionImage(); onActionImage();
@ -349,6 +363,9 @@ public class FragmentCompose extends FragmentBase {
case R.id.menu_attachment: case R.id.menu_attachment:
onActionAttachment(); onActionAttachment();
return true; return true;
case R.id.menu_link:
onActionLink();
return true;
default: default:
return false; return false;
} }
@ -1114,6 +1131,46 @@ public class FragmentCompose extends FragmentBase {
}); });
} }
private void onActionRecordAudio() {
Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent, ActivityCompose.REQUEST_RECORD_AUDIO);
}
private void onActionTakePhoto() {
File dir = new File(getContext().getFilesDir(), "temporary");
if (!dir.exists())
dir.mkdir();
File file = new File(dir, new Date().getTime() + ".jpg");
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
photoURI = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID, file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent, ActivityCompose.REQUEST_TAKE_PHOTO);
}
private void onActionImage() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
PackageManager pm = getContext().getPackageManager();
if (intent.resolveActivity(pm) == null)
Snackbar.make(view, R.string.title_no_saf, Snackbar.LENGTH_LONG).show();
else
startActivityForResult(Helper.getChooser(getContext(), intent), ActivityCompose.REQUEST_IMAGE);
}
private void onActionAttachment() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
PackageManager pm = getContext().getPackageManager();
if (intent.resolveActivity(pm) == null)
Snackbar.make(view, R.string.title_no_saf, Snackbar.LENGTH_LONG).show();
else
startActivityForResult(Helper.getChooser(getContext(), intent), ActivityCompose.REQUEST_ATTACHMENT);
}
private void onActionLink() { private void onActionLink() {
Uri uri = null; Uri uri = null;
@ -1191,29 +1248,6 @@ public class FragmentCompose extends FragmentBase {
}); });
} }
private void onActionImage() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
PackageManager pm = getContext().getPackageManager();
if (intent.resolveActivity(pm) == null)
Snackbar.make(view, R.string.title_no_saf, Snackbar.LENGTH_LONG).show();
else
startActivityForResult(Helper.getChooser(getContext(), intent), ActivityCompose.REQUEST_IMAGE);
}
private void onActionAttachment() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
PackageManager pm = getContext().getPackageManager();
if (intent.resolveActivity(pm) == null)
Snackbar.make(view, R.string.title_no_saf, Snackbar.LENGTH_LONG).show();
else
startActivityForResult(Helper.getChooser(getContext(), intent), ActivityCompose.REQUEST_ATTACHMENT);
}
private void onActionDelete() { private void onActionDelete() {
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner()) new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner())
.setMessage(R.string.title_ask_discard) .setMessage(R.string.title_ask_discard)
@ -1505,7 +1539,13 @@ public class FragmentCompose extends FragmentBase {
if (uri != null) if (uri != null)
handleAddAttachment(uri, true); handleAddAttachment(uri, true);
} }
} else if (requestCode == ActivityCompose.REQUEST_ATTACHMENT) { } else if (requestCode == ActivityCompose.REQUEST_ATTACHMENT ||
requestCode == ActivityCompose.REQUEST_RECORD_AUDIO ||
requestCode == ActivityCompose.REQUEST_TAKE_PHOTO) {
if (requestCode == ActivityCompose.REQUEST_TAKE_PHOTO)
data = new Intent().setData(photoURI);
if (data != null) { if (data != null) {
ClipData clipData = data.getClipData(); ClipData clipData = data.getClipData();
if (clipData == null) { if (clipData == null) {
@ -1722,11 +1762,11 @@ public class FragmentCompose extends FragmentBase {
private static EntityAttachment addAttachment(Context context, long id, Uri uri, private static EntityAttachment addAttachment(Context context, long id, Uri uri,
boolean image) throws IOException { boolean image) throws IOException {
if ("file".equals(uri.getScheme()) &&
!Helper.hasPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)) {
Log.w("Add attachment uri=" + uri); Log.w("Add attachment uri=" + uri);
if ("file".equals(uri.getScheme()) &&
!Helper.hasPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE))
throw new SecurityException(); throw new SecurityException();
}
EntityAttachment attachment = new EntityAttachment(); EntityAttachment attachment = new EntityAttachment();
@ -1805,6 +1845,15 @@ public class FragmentCompose extends FragmentBase {
} }
} }
if ("eu.faircode.email".equals(uri.getAuthority())) {
// content://eu.faircode.email/temporary/nnn.jpg
File tmp = new File(context.getFilesDir(), uri.getPath());
Log.i("Deleting " + tmp);
if (!tmp.delete())
Log.w("Error deleting " + tmp);
} else
Log.i("Authority=" + uri.getAuthority());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean autoresize = prefs.getBoolean("autoresize", true); boolean autoresize = prefs.getBoolean("autoresize", true);
@ -1821,6 +1870,7 @@ public class FragmentCompose extends FragmentBase {
options.outHeight / factor > resize) options.outHeight / factor > resize)
factor *= 2; factor *= 2;
Log.i("Image type=" + attachment.type + " rotation=" + getImageRotation(file));
Matrix rotation = ("image/jpeg".equals(attachment.type) ? getImageRotation(file) : null); Matrix rotation = ("image/jpeg".equals(attachment.type) ? getImageRotation(file) : null);
if (factor > 1 || rotation != null) { if (factor > 1 || rotation != null) {

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path
android:fillColor="@android:color/white"
android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M9,9m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"/>
<path
android:fillColor="@android:color/white"
android:pathData="M9,15c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4zM16.76,5.36l-1.68,1.69c0.84,1.18 0.84,2.71 0,3.89l1.68,1.69c2.02,-2.02 2.02,-5.07 0,-7.27zM20.07,2l-1.63,1.63c2.77,3.02 2.77,7.56 0,10.74L20.07,16c3.9,-3.89 3.91,-9.95 0,-14z"/>
</vector>

@ -1,9 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item <item
android:id="@+id/menu_link" android:id="@+id/menu_record_audio"
android:icon="@drawable/baseline_insert_link_24" android:icon="@drawable/baseline_record_voice_over_24"
android:title="@string/title_style_link" /> android:title="@string/title_attachment_audio" />
<item
android:id="@+id/menu_take_photo"
android:icon="@drawable/baseline_photo_camera_24"
android:title="@string/title_attachment_photo" />
<item <item
android:id="@+id/menu_image" android:id="@+id/menu_image"
@ -14,4 +19,9 @@
android:id="@+id/menu_attachment" android:id="@+id/menu_attachment"
android:icon="@drawable/baseline_attachment_24" android:icon="@drawable/baseline_attachment_24"
android:title="@string/title_add_attachment" /> android:title="@string/title_add_attachment" />
<item
android:id="@+id/menu_link"
android:icon="@drawable/baseline_insert_link_24"
android:title="@string/title_style_link" />
</menu> </menu>

@ -461,6 +461,9 @@
<string name="title_style_image">Insert image</string> <string name="title_style_image">Insert image</string>
<string name="title_style_toolbar">Style toolbar</string> <string name="title_style_toolbar">Style toolbar</string>
<string name="title_add_attachment">Add attachment</string> <string name="title_add_attachment">Add attachment</string>
<string name="title_attachment_file">Attach file</string>
<string name="title_attachment_photo">Take photo</string>
<string name="title_attachment_audio">Record audio</string>
<string name="title_show_addresses">Show CC/BCC</string> <string name="title_show_addresses">Show CC/BCC</string>
<string name="title_insert_contact_group">Insert contact group</string> <string name="title_insert_contact_group">Insert contact group</string>
<string name="title_insert_template">Insert template</string> <string name="title_insert_template">Insert template</string>

@ -6,4 +6,7 @@
<files-path <files-path
name="raw" name="raw"
path="raw" /> path="raw" />
<files-path
name="temporary"
path="temporary" />
</paths> </paths>

Loading…
Cancel
Save