Java 具有多个附件的Android电子邮件意图

Java 具有多个附件的Android电子邮件意图,java,android,attachment,email-attachments,Java,Android,Attachment,Email Attachments,我正在开发一个应用程序,用户可以填写一张成绩单,然后通过选择的电子邮件客户端(我的例子是Gmail)发送。除了文本,用户需要能够附加一个或多个图像,但我似乎无法让它工作(完整的代码附加到更下面) 下面是onActivityResult,它将图像附加到视图,并将其URI放入“userSelectedImageUriList”中。这似乎奏效了 @Override protected void onActivityResult(int requestCode, int resultCode, Inte

我正在开发一个应用程序,用户可以填写一张成绩单,然后通过选择的电子邮件客户端(我的例子是Gmail)发送。除了文本,用户需要能够附加一个或多个图像,但我似乎无法让它工作(完整的代码附加到更下面)

下面是onActivityResult,它将图像附加到视图,并将其URI放入“userSelectedImageUriList”中。这似乎奏效了

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode==REQUEST_CODE_BROWSE_PICTURE)
    {
        if(resultCode==RESULT_OK)
        {
            // Get return image uri. If select the image from camera the uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
            // If select the image from gallery the uri like content://media/external/images/media/1316970.
            Uri fileUri = data.getData();

            // Save user choose image file uri in list.
            if(userSelectedImageUriList == null)
            {
                userSelectedImageUriList = new ArrayList<Uri>();
            }
            userSelectedImageUriList.add(fileUri);

            // Create content resolver.
            ContentResolver contentResolver = getContentResolver();

            try {
                // Open the file input stream by the uri.
                InputStream inputStream = contentResolver.openInputStream(fileUri);

                // Get the bitmap.
                Bitmap imgBitmap = BitmapFactory.decodeStream(inputStream);

                ImageView imageview = new ImageView(ReportCard.this);
                LinearLayout linearLayout = (LinearLayout)findViewById(R.id.imageHolderLayout);
                LinearLayout.LayoutParams params = new LinearLayout
                        .LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

                // Add image path from drawable folder.
                imageview.setImageBitmap(imgBitmap);
                imageview.setLayoutParams(params);
                linearLayout.addView(imageview);

                inputStream.close();
            }catch(FileNotFoundException ex)
            {
                Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
            }catch(IOException ex)
            {
                Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
            }
        }
    }
}
现在,一切都停止了。将显示选择器,但不会附加图像。Gmail将打开,但会显示一个带有“无法附加文件”的toast

完整代码 ReportCard.java

package com.zaewin.reports;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

public class ReportCard extends Activity {
    long reportID;
    long newRowId;
    // Log tag that is used to distinguish log info.
    private final static String TAG_BROWSE_PICTURE = "BROWSE_PICTURE";

    // Used when request action Intent.ACTION_GET_CONTENT
    private final static int REQUEST_CODE_BROWSE_PICTURE = 1;

    // Used when request read external storage permission.
    private final static int REQUEST_PERMISSION_READ_EXTERNAL = 2;

    // Save user selected image uri list.
    private ArrayList<Uri> userSelectedImageUriList = null;

    // Currently displayed user selected image index in userSelectedImageUriList.
    private int currentDisplayedUserSelectImageIndex = 0;

    @Override
    public void onBackPressed() {
        saveReport(ReportCard.this);
        finish();
    }

    // create an action bar button
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.reportmenu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    // handle button activities
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.deleteButton:
                new AlertDialog.Builder(this)
                    .setTitle(R.string.delete)
                    .setMessage(R.string.delete_prompt)
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            Bundle bundle = getIntent().getExtras();
                            Boolean deletestatus = deleteReport(getApplicationContext(), bundle.getInt("reportID"));

                            if(deletestatus == true) {
                                CharSequence text = getString(R.string.delete_success);
                                Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
                                toast.show();
                                finish();
                            } else {
                                CharSequence text = getString(R.string.delete_fail);
                                Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
                                toast.show();
                            }
                        }})
                    .setNegativeButton(android.R.string.no, null).show();
                return true;

            case R.id.saveButton:
                saveReport(getApplicationContext());
                return true;

            case R.id.sendButton:
                sendReport(getApplicationContext());
                return true;

            default:
                // If we got here, the user's action was not recognized.
                // Invoke the superclass to handle it.
                return super.onOptionsItemSelected(item);

        }
    }

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.report_view);
        setTitle(R.string.report_card);

        Bundle bundle = getIntent().getExtras();
        if(bundle != null) {
            reportID = bundle.getInt("reportID");
            loadReport(reportID);
        } else {
            setDefaults();
        }

        final Button button = (Button) findViewById(R.id.buttonAddPicture);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Because camera app returned uri value is something like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
                // So if show the camera image in image view, this app require below permission.
                int readExternalStoragePermission = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE);
                if(readExternalStoragePermission != PackageManager.PERMISSION_GRANTED)
                {
                    String requirePermission[] = {Manifest.permission.READ_EXTERNAL_STORAGE};
                    ActivityCompat.requestPermissions(ReportCard.this, requirePermission, REQUEST_PERMISSION_READ_EXTERNAL);
                }else {
                    openPictureGallery();
                }
            }
        });
    }

    /* Invoke android os system file browser to select images. */
    private void openPictureGallery()
    {
        // Create an intent.
        Intent openAlbumIntent = new Intent();

        // Only show images in the content chooser.
        // If you want to select all type data then openAlbumIntent.setType("*/*");
        // Must set type for the intent, otherwise there will throw android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT }
        openAlbumIntent.setType("image/*");

        // Set action, this action will invoke android os browse content app.
        openAlbumIntent.setAction(Intent.ACTION_GET_CONTENT);

        // Start the activity.
        startActivityForResult(openAlbumIntent, REQUEST_CODE_BROWSE_PICTURE);
    }

    /* When the action Intent.ACTION_GET_CONTENT invoked app return, this method will be executed. */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==REQUEST_CODE_BROWSE_PICTURE)
        {
            if(resultCode==RESULT_OK)
            {
                // Get return image uri. If select the image from camera the uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
                // If select the image from gallery the uri like content://media/external/images/media/1316970.
                Uri fileUri = data.getData();

                // Save user choose image file uri in list.
                if(userSelectedImageUriList == null)
                {
                    userSelectedImageUriList = new ArrayList<Uri>();
                }
                userSelectedImageUriList.add(fileUri);

                // Create content resolver.
                ContentResolver contentResolver = getContentResolver();

                try {
                    // Open the file input stream by the uri.
                    InputStream inputStream = contentResolver.openInputStream(fileUri);

                    // Get the bitmap.
                    Bitmap imgBitmap = BitmapFactory.decodeStream(inputStream);

                    ImageView imageview = new ImageView(ReportCard.this);
                    LinearLayout linearLayout = (LinearLayout)findViewById(R.id.imageHolderLayout);
                    LinearLayout.LayoutParams params = new LinearLayout
                            .LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

                    // Add image path from drawable folder.
                    imageview.setImageBitmap(imgBitmap);
                    imageview.setLayoutParams(params);
                    linearLayout.addView(imageview);

                    inputStream.close();
                }catch(FileNotFoundException ex)
                {
                    Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
                }catch(IOException ex)
                {
                    Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
                }
            }
        }
    }

    /* After user choose grant read external storage permission or not. */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode==REQUEST_PERMISSION_READ_EXTERNAL)
        {
            if(grantResults.length > 0)
            {
                int grantResult = grantResults[0];
                if(grantResult == PackageManager.PERMISSION_GRANTED)
                {
                    // If user grant the permission then open choose image popup dialog.
                    openPictureGallery();
                }else
                {
                    Toast.makeText(getApplicationContext(), "You denied read external storage permission.", Toast.LENGTH_LONG).show();
                }
            }
        }
    }

    public void setDefaults()  {
        EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
        emailField.setText(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("report_email", ""), TextView.BufferType.EDITABLE);

        EditText nameField = (EditText)findViewById(R.id.EditTextName);
        nameField.setText(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("report_name", ""), TextView.BufferType.EDITABLE);

        Calendar c = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String formattedDate = df.format(c.getTime());

        EditText dateField = (EditText)findViewById(R.id.EditTextDate);
        dateField.setText(formattedDate, TextView.BufferType.EDITABLE);
    }

    public void loadReport(long reportID) {
        ReportDbHelper mDbHelper = new ReportDbHelper(getBaseContext());
        SQLiteDatabase db = mDbHelper.getReadableDatabase();

        // Define a projection that specifies which columns from the database
        // you will actually use after this query.
        String[] projection = {
                ReportContract.ReportEntry._ID,
                ReportContract.ReportEntry.COLUMN_NAME,
                ReportContract.ReportEntry.COLUMN_EMAIL,
                ReportContract.ReportEntry.COLUMN_LOCATION,
                ReportContract.ReportEntry.COLUMN_DATE,
                ReportContract.ReportEntry.COLUMN_BODY
        };

        // Filter results WHERE "title" = 'My Title'
        String selection = ReportContract.ReportEntry._ID + " = ?";
        String[] selectionArgs = { Long.toString(reportID) };

        // How you want the results sorted in the resulting Cursor
        String sortOrder = ReportContract.ReportEntry.COLUMN_NAME + " DESC";

        Cursor cursor = db.query(
                ReportContract.ReportEntry.TABLE_NAME,                     // The table to query
                projection,                               // The columns to return
                selection,                                // The columns for the WHERE clause
                selectionArgs,                            // The values for the WHERE clause
                null,                                     // don't group the rows
                null,                                     // don't filter by row groups
                sortOrder                                 // The sort order
        );


        //List itemIds = new ArrayList<>();
        while(cursor.moveToNext()) {
            EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
            emailField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_EMAIL)), TextView.BufferType.EDITABLE);

            EditText nameField = (EditText)findViewById(R.id.EditTextName);
            nameField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_NAME)), TextView.BufferType.EDITABLE);

            EditText dateField = (EditText)findViewById(R.id.EditTextDate);
            dateField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_DATE)), TextView.BufferType.EDITABLE);

            EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
            locationField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_LOCATION)), TextView.BufferType.EDITABLE);

            EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
            bodyField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_BODY)), TextView.BufferType.EDITABLE);
        }
        cursor.close();
        db.close();
    }

    public long saveReport(Context context) {
        EditText nameField = (EditText)findViewById(R.id.EditTextName);
        EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
        EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
        EditText dateField = (EditText)findViewById(R.id.EditTextDate);
        EditText bodyField = (EditText)findViewById(R.id.EditTextBody);

        ReportDbHelper mDbHelper = new ReportDbHelper(context);
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        // Create a new map of values, where column names are the keys
        ContentValues values = new ContentValues();
        values.put(ReportContract.ReportEntry.COLUMN_NAME, nameField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_EMAIL, emailField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_LOCATION, locationField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_DATE, dateField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_BODY, bodyField.getText().toString());

        CharSequence text;
        try {
            if(reportID == 0) {
                newRowId = db.insert(ReportContract.ReportEntry.TABLE_NAME, null, values);
                text = getString(R.string.save_success);
            } else {
                String where = ReportContract.ReportEntry._ID + " = ?";
                String[] whereArgs = new String[]{String.valueOf(reportID)};

                newRowId = db.update(ReportContract.ReportEntry.TABLE_NAME, values, where, whereArgs);
                text = getString(R.string.update_success);
            }
            Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
            toast.show();
            //finish();
        } catch(android.database.sqlite.SQLiteException ex) {
            text = getString(R.string.save_error);
            Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
            toast.show();
        }
        db.close();

        return newRowId;
    }

    public boolean deleteReport(Context context, Integer reportID) {
        ReportDbHelper mDbHelper = new ReportDbHelper(context);
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        Boolean status = db.delete(ReportContract.ReportEntry.TABLE_NAME, ReportContract.ReportEntry._ID + "=" + reportID, null) > 0;
        db.close();
        return status;
    }

    public void sendReport(Context context) {
        EditText nameField = (EditText)findViewById(R.id.EditTextName);
        EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
        EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
        EditText dateField = (EditText)findViewById(R.id.EditTextDate);
        EditText bodyField = (EditText)findViewById(R.id.EditTextBody);

        if(!nameField.getText().toString().matches("") && !emailField.getText().toString().matches("") && !locationField.getText().toString().matches("") && !dateField.getText().toString().matches("") && !bodyField.getText().toString().matches("")) {
            PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_email", emailField.getText().toString()).commit();
            PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_name", nameField.getText().toString()).commit();

            String emailBody = "Ditt namn: "+nameField.getText()+"\n\n";
            emailBody += "Plats: "+locationField.getText()+"\n\n";
            emailBody += "Tidpunkt: "+dateField.getText()+"\n\n";
            emailBody += "Beskrivning: "+bodyField.getText();

            Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);

            ArrayList<Uri> uris = new ArrayList<Uri>();
            for (Uri file : userSelectedImageUriList)
            {
                File fileIn = new File(file.toString());
                fileIn.setReadable(true, false);
                Uri u = Uri.fromFile(fileIn);
                uris.add(u);
            }

            // set the type to 'email'
            emailIntent.setType("text/plain");
            String to[] = {emailField.getText().toString()};
            emailIntent.putExtra(Intent.EXTRA_EMAIL, to);

            // the attachment
            emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

            // the mail
            emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Rapport från Hamnarbetarappen");
            emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);

            startActivity(Intent.createChooser(emailIntent , "Skicka med..."));
            finish();
        } else {
            Toast.makeText(this, getString(R.string.field_error), Toast.LENGTH_SHORT).show();
        }
    }
}
package com.zaewin.reports;
导入android.Manifest;
导入android.app.Activity;
导入android.app.AlertDialog;
导入android.content.ContentResolver;
导入android.content.ContentValues;
导入android.content.Context;
导入android.content.DialogInterface;
导入android.content.Intent;
导入android.content.pm.PackageManager;
导入android.database.Cursor;
导入android.database.sqlite.SQLiteDatabase;
导入android.graphics.Bitmap;
导入android.graphics.BitmapFactory;
导入android.net.Uri;
导入android.os.Bundle;
导入android.preference.PreferenceManager;
导入android.support.annotation.NonNull;
导入android.support.v4.app.ActivityCompat;
导入android.support.v4.content.ContextCompat;
导入android.util.Log;
导入android.view.Menu;
导入android.view.MenuItem;
导入android.view.view;
导入android.widget.Button;
导入android.widget.EditText;
导入android.widget.ImageView;
导入android.widget.LinearLayout;
导入android.widget.TextView;
导入android.widget.Toast;
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.io.IOException;
导入java.io.InputStream;
导入java.text.simpleDataFormat;
导入java.util.ArrayList;
导入java.util.Calendar;
公共类报表卡扩展活动{
长报告ID;
长纽罗维德;
//用于区分日志信息的日志标记。
私有最终静态字符串标记\u BROWSE\u PICTURE=“BROWSE\u PICTURE”;
//请求操作意图时使用。操作获取内容
私有最终静态整数请求\代码\浏览\图片=1;
//请求读取外部存储权限时使用。
私有最终静态int请求\权限\读取\外部=2;
//保存用户选择的图像uri列表。
private ArrayList userSelectedImageUriList=null;
//在UserSelectedImage列表中当前显示的用户选择的图像索引。
private int currentDisplayedUserSelectImageIndex=0;
@凌驾
public void onBackPressed(){
saveReport(ReportCard.this);
完成();
}
//创建一个操作栏按钮
@凌驾
公共布尔onCreateOptions菜单(菜单){
getMenuInflater().充气(R.menu.reportmenu,menu);
返回super.onCreateOptions菜单(菜单);
}
//处理按钮活动
@凌驾
公共布尔值onOptionsItemSelected(菜单项项){
开关(item.getItemId()){
案例R.id.delete按钮:
新建AlertDialog.Builder(此)
.setTitle(R.string.delete)
.setMessage(R.string.delete_提示符)
.setIcon(android.R.drawable.ic_对话框_警报)
.setPositiveButton(android.R.string.yes,新的DialogInterface.OnClickListener(){
public void onClick(对话框接口对话框,int whichButton){
Bundle Bundle=getIntent().getExtras();
布尔deletestatus=deleteReport(getApplicationContext(),bundle.getInt(“reportID”);
if(deletestatus==true){
CharSequence text=getString(R.string.delete\u成功);
Toast Toast=Toast.makeText(getApplicationContext(),text,Toast.LENGTH\u SHORT);
toast.show();
完成();
}否则{
CharSequence text=getString(R.string.delete\u失败);
Toast Toast=Toast.makeText(getApplicationContext(),text,Toast.LENGTH\u SHORT);
toast.show();
}
}})
.setNegativeButton(android.R.string.no,null).show();
返回true;
案例R.id.saveButton:
saveReport(getApplicationContext());
返回true;
案例R.id.sendButton:
sendReport(getApplicationContext());
返回true;
违约:
//如果我们到了这里,用户的行为就不会被识别。
//调用超类来处理它。
返回super.onOptionsItemSelected(项目);
}
}
@凌驾
创建公共空间(捆绑冰柱){
超级冰柱;
setContentView(R.layout.report\u视图);
setTitle(R.string.报告卡);
Bundle Bundle=getIntent().getExtras();
if(bundle!=null){
reportID=bundle.getInt(“reportID”);
loadReport(reportID);
}否则{
setDefaults();
}
最终按钮按钮=(按钮)findViewById(R.id.buttonAddPicture);
setOnClickListener(新视图.OnClickListener(){
公共void onClick(视图v){
//因为摄像头应用程序返回的uri值类似于file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
//因此,如果在图像视图中显示相机图像,此应用程序需要以下权限。
int readExternalStoragePermission=ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.READ\u EXTERNAL\u STORAGE);
if(readExternalStoragePermission!=已授予PackageManager.PERMISSION)
package com.zaewin.reports;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

public class ReportCard extends Activity {
    long reportID;
    long newRowId;
    // Log tag that is used to distinguish log info.
    private final static String TAG_BROWSE_PICTURE = "BROWSE_PICTURE";

    // Used when request action Intent.ACTION_GET_CONTENT
    private final static int REQUEST_CODE_BROWSE_PICTURE = 1;

    // Used when request read external storage permission.
    private final static int REQUEST_PERMISSION_READ_EXTERNAL = 2;

    // Save user selected image uri list.
    private ArrayList<Uri> userSelectedImageUriList = null;

    // Currently displayed user selected image index in userSelectedImageUriList.
    private int currentDisplayedUserSelectImageIndex = 0;

    @Override
    public void onBackPressed() {
        saveReport(ReportCard.this);
        finish();
    }

    // create an action bar button
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.reportmenu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    // handle button activities
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.deleteButton:
                new AlertDialog.Builder(this)
                    .setTitle(R.string.delete)
                    .setMessage(R.string.delete_prompt)
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            Bundle bundle = getIntent().getExtras();
                            Boolean deletestatus = deleteReport(getApplicationContext(), bundle.getInt("reportID"));

                            if(deletestatus == true) {
                                CharSequence text = getString(R.string.delete_success);
                                Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
                                toast.show();
                                finish();
                            } else {
                                CharSequence text = getString(R.string.delete_fail);
                                Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
                                toast.show();
                            }
                        }})
                    .setNegativeButton(android.R.string.no, null).show();
                return true;

            case R.id.saveButton:
                saveReport(getApplicationContext());
                return true;

            case R.id.sendButton:
                sendReport(getApplicationContext());
                return true;

            default:
                // If we got here, the user's action was not recognized.
                // Invoke the superclass to handle it.
                return super.onOptionsItemSelected(item);

        }
    }

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.report_view);
        setTitle(R.string.report_card);

        Bundle bundle = getIntent().getExtras();
        if(bundle != null) {
            reportID = bundle.getInt("reportID");
            loadReport(reportID);
        } else {
            setDefaults();
        }

        final Button button = (Button) findViewById(R.id.buttonAddPicture);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Because camera app returned uri value is something like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
                // So if show the camera image in image view, this app require below permission.
                int readExternalStoragePermission = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE);
                if(readExternalStoragePermission != PackageManager.PERMISSION_GRANTED)
                {
                    String requirePermission[] = {Manifest.permission.READ_EXTERNAL_STORAGE};
                    ActivityCompat.requestPermissions(ReportCard.this, requirePermission, REQUEST_PERMISSION_READ_EXTERNAL);
                }else {
                    openPictureGallery();
                }
            }
        });
    }

    /* Invoke android os system file browser to select images. */
    private void openPictureGallery()
    {
        // Create an intent.
        Intent openAlbumIntent = new Intent();

        // Only show images in the content chooser.
        // If you want to select all type data then openAlbumIntent.setType("*/*");
        // Must set type for the intent, otherwise there will throw android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT }
        openAlbumIntent.setType("image/*");

        // Set action, this action will invoke android os browse content app.
        openAlbumIntent.setAction(Intent.ACTION_GET_CONTENT);

        // Start the activity.
        startActivityForResult(openAlbumIntent, REQUEST_CODE_BROWSE_PICTURE);
    }

    /* When the action Intent.ACTION_GET_CONTENT invoked app return, this method will be executed. */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==REQUEST_CODE_BROWSE_PICTURE)
        {
            if(resultCode==RESULT_OK)
            {
                // Get return image uri. If select the image from camera the uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
                // If select the image from gallery the uri like content://media/external/images/media/1316970.
                Uri fileUri = data.getData();

                // Save user choose image file uri in list.
                if(userSelectedImageUriList == null)
                {
                    userSelectedImageUriList = new ArrayList<Uri>();
                }
                userSelectedImageUriList.add(fileUri);

                // Create content resolver.
                ContentResolver contentResolver = getContentResolver();

                try {
                    // Open the file input stream by the uri.
                    InputStream inputStream = contentResolver.openInputStream(fileUri);

                    // Get the bitmap.
                    Bitmap imgBitmap = BitmapFactory.decodeStream(inputStream);

                    ImageView imageview = new ImageView(ReportCard.this);
                    LinearLayout linearLayout = (LinearLayout)findViewById(R.id.imageHolderLayout);
                    LinearLayout.LayoutParams params = new LinearLayout
                            .LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

                    // Add image path from drawable folder.
                    imageview.setImageBitmap(imgBitmap);
                    imageview.setLayoutParams(params);
                    linearLayout.addView(imageview);

                    inputStream.close();
                }catch(FileNotFoundException ex)
                {
                    Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
                }catch(IOException ex)
                {
                    Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
                }
            }
        }
    }

    /* After user choose grant read external storage permission or not. */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode==REQUEST_PERMISSION_READ_EXTERNAL)
        {
            if(grantResults.length > 0)
            {
                int grantResult = grantResults[0];
                if(grantResult == PackageManager.PERMISSION_GRANTED)
                {
                    // If user grant the permission then open choose image popup dialog.
                    openPictureGallery();
                }else
                {
                    Toast.makeText(getApplicationContext(), "You denied read external storage permission.", Toast.LENGTH_LONG).show();
                }
            }
        }
    }

    public void setDefaults()  {
        EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
        emailField.setText(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("report_email", ""), TextView.BufferType.EDITABLE);

        EditText nameField = (EditText)findViewById(R.id.EditTextName);
        nameField.setText(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("report_name", ""), TextView.BufferType.EDITABLE);

        Calendar c = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String formattedDate = df.format(c.getTime());

        EditText dateField = (EditText)findViewById(R.id.EditTextDate);
        dateField.setText(formattedDate, TextView.BufferType.EDITABLE);
    }

    public void loadReport(long reportID) {
        ReportDbHelper mDbHelper = new ReportDbHelper(getBaseContext());
        SQLiteDatabase db = mDbHelper.getReadableDatabase();

        // Define a projection that specifies which columns from the database
        // you will actually use after this query.
        String[] projection = {
                ReportContract.ReportEntry._ID,
                ReportContract.ReportEntry.COLUMN_NAME,
                ReportContract.ReportEntry.COLUMN_EMAIL,
                ReportContract.ReportEntry.COLUMN_LOCATION,
                ReportContract.ReportEntry.COLUMN_DATE,
                ReportContract.ReportEntry.COLUMN_BODY
        };

        // Filter results WHERE "title" = 'My Title'
        String selection = ReportContract.ReportEntry._ID + " = ?";
        String[] selectionArgs = { Long.toString(reportID) };

        // How you want the results sorted in the resulting Cursor
        String sortOrder = ReportContract.ReportEntry.COLUMN_NAME + " DESC";

        Cursor cursor = db.query(
                ReportContract.ReportEntry.TABLE_NAME,                     // The table to query
                projection,                               // The columns to return
                selection,                                // The columns for the WHERE clause
                selectionArgs,                            // The values for the WHERE clause
                null,                                     // don't group the rows
                null,                                     // don't filter by row groups
                sortOrder                                 // The sort order
        );


        //List itemIds = new ArrayList<>();
        while(cursor.moveToNext()) {
            EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
            emailField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_EMAIL)), TextView.BufferType.EDITABLE);

            EditText nameField = (EditText)findViewById(R.id.EditTextName);
            nameField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_NAME)), TextView.BufferType.EDITABLE);

            EditText dateField = (EditText)findViewById(R.id.EditTextDate);
            dateField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_DATE)), TextView.BufferType.EDITABLE);

            EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
            locationField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_LOCATION)), TextView.BufferType.EDITABLE);

            EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
            bodyField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_BODY)), TextView.BufferType.EDITABLE);
        }
        cursor.close();
        db.close();
    }

    public long saveReport(Context context) {
        EditText nameField = (EditText)findViewById(R.id.EditTextName);
        EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
        EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
        EditText dateField = (EditText)findViewById(R.id.EditTextDate);
        EditText bodyField = (EditText)findViewById(R.id.EditTextBody);

        ReportDbHelper mDbHelper = new ReportDbHelper(context);
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        // Create a new map of values, where column names are the keys
        ContentValues values = new ContentValues();
        values.put(ReportContract.ReportEntry.COLUMN_NAME, nameField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_EMAIL, emailField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_LOCATION, locationField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_DATE, dateField.getText().toString());
        values.put(ReportContract.ReportEntry.COLUMN_BODY, bodyField.getText().toString());

        CharSequence text;
        try {
            if(reportID == 0) {
                newRowId = db.insert(ReportContract.ReportEntry.TABLE_NAME, null, values);
                text = getString(R.string.save_success);
            } else {
                String where = ReportContract.ReportEntry._ID + " = ?";
                String[] whereArgs = new String[]{String.valueOf(reportID)};

                newRowId = db.update(ReportContract.ReportEntry.TABLE_NAME, values, where, whereArgs);
                text = getString(R.string.update_success);
            }
            Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
            toast.show();
            //finish();
        } catch(android.database.sqlite.SQLiteException ex) {
            text = getString(R.string.save_error);
            Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
            toast.show();
        }
        db.close();

        return newRowId;
    }

    public boolean deleteReport(Context context, Integer reportID) {
        ReportDbHelper mDbHelper = new ReportDbHelper(context);
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        Boolean status = db.delete(ReportContract.ReportEntry.TABLE_NAME, ReportContract.ReportEntry._ID + "=" + reportID, null) > 0;
        db.close();
        return status;
    }

    public void sendReport(Context context) {
        EditText nameField = (EditText)findViewById(R.id.EditTextName);
        EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
        EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
        EditText dateField = (EditText)findViewById(R.id.EditTextDate);
        EditText bodyField = (EditText)findViewById(R.id.EditTextBody);

        if(!nameField.getText().toString().matches("") && !emailField.getText().toString().matches("") && !locationField.getText().toString().matches("") && !dateField.getText().toString().matches("") && !bodyField.getText().toString().matches("")) {
            PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_email", emailField.getText().toString()).commit();
            PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_name", nameField.getText().toString()).commit();

            String emailBody = "Ditt namn: "+nameField.getText()+"\n\n";
            emailBody += "Plats: "+locationField.getText()+"\n\n";
            emailBody += "Tidpunkt: "+dateField.getText()+"\n\n";
            emailBody += "Beskrivning: "+bodyField.getText();

            Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);

            ArrayList<Uri> uris = new ArrayList<Uri>();
            for (Uri file : userSelectedImageUriList)
            {
                File fileIn = new File(file.toString());
                fileIn.setReadable(true, false);
                Uri u = Uri.fromFile(fileIn);
                uris.add(u);
            }

            // set the type to 'email'
            emailIntent.setType("text/plain");
            String to[] = {emailField.getText().toString()};
            emailIntent.putExtra(Intent.EXTRA_EMAIL, to);

            // the attachment
            emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

            // the mail
            emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Rapport från Hamnarbetarappen");
            emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);

            startActivity(Intent.createChooser(emailIntent , "Skicka med..."));
            finish();
        } else {
            Toast.makeText(this, getString(R.string.field_error), Toast.LENGTH_SHORT).show();
        }
    }
}
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ScrollView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scrollbars="vertical">
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp">        
        <EditText
            android:id="@+id/EditTextName"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/report_name"
            android:inputType="textPersonName" >
        </EditText>
        <EditText
            android:id="@+id/EditTextEmail"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/report_email"
            android:inputType="textEmailAddress" >
        </EditText>
        <EditText
            android:id="@+id/EditTextLocation"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/report_location" >
        </EditText>
        <EditText
            android:id="@+id/EditTextDate"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/report_date"
            android:inputType="datetime" >
        </EditText>
        <EditText
            android:id="@+id/EditTextBody"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/report_description"
            android:inputType="textMultiLine"
            android:lines="5" >
        </EditText>        
        <LinearLayout
        android:id="@+id/relativeLayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="5dp">
            <Button
                android:id="@+id/buttonAddPicture"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="@drawable/blue_button"
                android:drawableRight="@drawable/ic_action_camera"
                android:padding="10dp"
                android:text="@string/report_takepicture"
                android:textAlignment="center"
                android:textColor="@color/actionbar_text" />
       </LinearLayout>
    <LinearLayout
        android:id="@+id/imageHolderLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginBottom="5dp">
    </LinearLayout>
</ScrollView>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zaewin.reports" android:versionCode="1" android:versionName="1.0">
    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="22" />
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:required="true" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="true" />
    <uses-permission android:name="android.permission.INTERNET" android:required="true"/>

    <application android:theme="@style/CustomActionBarTheme" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:allowBackup="true">        
        <activity android:label="ReportCard" android:screenOrientation="portrait" android:configChanges="orientation|keyboardHidden" android:name=".ReportCard">
            <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ReportList" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>        
    </application>
</manifest>
public void sendReport(Context context) {
    EditText nameField = (EditText)findViewById(R.id.EditTextName);
    EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
    EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
    EditText dateField = (EditText)findViewById(R.id.EditTextDate);
    EditText bodyField = (EditText)findViewById(R.id.EditTextBody);

    if(!nameField.getText().toString().matches("") && !emailField.getText().toString().matches("") && !locationField.getText().toString().matches("") && !dateField.getText().toString().matches("") && !bodyField.getText().toString().matches("")) {
        PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_email", emailField.getText().toString()).apply();
        PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_name", nameField.getText().toString()).apply();

        String emailBody = "Name: "+nameField.getText()+"\n\n";
        emailBody += "Location: "+locationField.getText()+"\n\n";
        emailBody += "Time: "+dateField.getText()+"\n\n";
        emailBody += "Description: "+bodyField.getText();

        Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);

        // set the type to 'email'
        emailIntent.setType("text/plain");
        String to[] = {emailField.getText().toString()};
        emailIntent.putExtra(Intent.EXTRA_EMAIL, to);

        // the attachment - ArrayList populated in onActivityResult
        emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, userSelectedImageUriList);

        // the mail
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Report);
        emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);

        startActivity(Intent.createChooser(emailIntent , "Send with..."));
        //finish();
    } else {
        Toast.makeText(this, getString(R.string.field_error), Toast.LENGTH_SHORT).show();
    }
}