首页 > 其他分享 >app混合开发,选择相册和相机功能

app混合开发,选择相册和相机功能

时间:2023-03-24 15:57:39浏览次数:36  
标签:相册 app 相机 Intent dialog new import android intent

原生:安卓 , IOS

前端:vue

目标:前端 input type=file 实现调用原生相机和图片,选择并返回前台照片

前提:安卓调用和访问权限一添加

原生: 

dWebView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                mFileCallback = filePathCallback;
                MODE_OPEN_MULTIPLE = fileChooserParams.getMode();
                showImageSelectDialog();
                return true;
            }
});
onShowFileChooser 获取 input的信息


安卓端弹窗开发

 

//自主选择相机或者相册dialog
    private boolean isClick = false;

    private void showImageSelectDialog() {
        isClick = false;
        final Dialog dialog = new Dialog(this, R.style.Dialog);
        View view = View.inflate(this, R.layout.dialog_custom_layout, null);
        dialog.setContentView(view);

        Window window = dialog.getWindow();
        window.setGravity(Gravity.BOTTOM);
        window.setWindowAnimations(R.style.main_menu_animStyle);
        window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        dialog.show();

        //打开相机按钮
        dialog.findViewById(R.id.tv_take_photo).setOnClickListener(view1 -> {
            isClick = true;
            openCamera();
            dialog.dismiss();
        });
        //打开相册按钮
        dialog.findViewById(R.id.tv_take_pic).setOnClickListener(view2 -> {
            isClick = true;
            takePhoto();
            dialog.dismiss();
        });

        //取消按钮
        dialog.findViewById(R.id.tv_cancel).setOnClickListener(view3 -> dialog.dismiss());
        //关闭dialog
        dialog.setOnDismissListener(dialog1 -> {
            if ( ! isClick ) {
                mFileCallback.onReceiveValue(null);
            }
        });
    }

开发打开相机

//打开相机
    private void openCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File p = Environment.getExternalStorageDirectory();
        File dir = new File(FileUtil.getImageTempPath());
        if ( ! dir.exists() ) {
            dir.mkdirs();
        }
        String picName = System.currentTimeMillis() + ".jpg";
        String appId = ConfigUtils.getFieldBuildConfig("APPLICATION_ID");
        File photoFile = new File(FileUtil.getImageTempPath() + picName);
        if ( Build.VERSION.SDK_INT >= 24 ) {
            Uri uri = FileProvider.getUriForFile(context, appId + ".fileprovider", photoFile);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        } else {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        }
        CacheUtils.getInstance().setCameraPhotoPath(this, photoFile.getAbsolutePath());
        startActivityForResult(intent, REQUEST_CODE_CAMERA);
    }

打开相册

//打开相册
    private void takePhoto() {
        //传递读取本地相册意图
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        if(MODE_OPEN_MULTIPLE == 1){
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        }
        // 判断系统中是否有处理该 Intent 的 Activity
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(Intent.createChooser(intent, "Select Picture"), REQUEST_CODE_PICTURE);
        } else {
            Toast.makeText(MainActivity.this, "未找到图片查看器", Toast.LENGTH_SHORT).show();
        }
    }

处理回调

@Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {


        //input控件相关回调设置
        if ( resultCode == RESULT_OK ) {
            switch (requestCode) {
                case REQUEST_CODE_CAMERA:
                    String path = CacheUtils.getInstance().getCameraPhotoPath(this);
                    File file = new File(path);
                    if ( file.exists() ) {
                        mFileCallback.onReceiveValue(new Uri[]{Uri.fromFile(file)});
                    } else {
                        mFileCallback.onReceiveValue(null);
                    }
                    mFileCallback = null;
                    break;
                case REQUEST_CODE_PICTURE:
                    if(data != null){
                        Uri uri = data.getData();
                        List<Uri> uriList = new ArrayList<>();
                        if (uri != null) {
                            //没设置Intent.EXTRA_ALLOW_MULTIPLE,会回调这个
                            uriList.add(uri);
                        } else if (data.getClipData() != null) {
                            //设置Intent.EXTRA_ALLOW_MULTIPLE,会回调这个
                            ClipData clipData = data.getClipData();
                            int count = clipData.getItemCount();
                            if(count > 0){
                                for (int i=0; i<count; i++){
                                    Uri imageUri =clipData.getItemAt(i).getUri();
                                    uriList.add(imageUri);
                                }
                            }else {
                                Toast.makeText(context , "获取数据为空", Toast.LENGTH_LONG).show();
                            }
                        } else {
                            Toast.makeText(context , "获取数据为空", Toast.LENGTH_LONG).show();
                        }
                        if(CollectionUtil.isNotEmpty(uriList)){
                            Uri[] uris = uriList.toArray(new Uri[uriList.size()]);
                            mFileCallback.onReceiveValue(uris);
                        }
                    } else {
                        Toast.makeText(context , "获取数据为空", Toast.LENGTH_LONG).show();
                    }
                    mFileCallback = null;
                    break;
                default:
                    break;
            }
        }
        if ( mFileCallback != null ) {
            mFileCallback.onReceiveValue(null);
            mFileCallback = null;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

 

弹窗画面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_take_photo"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="拍摄"
        android:textColor="@android:color/background_dark"
        android:textSize="16sp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="#1a000000" />

    <TextView
        android:id="@+id/tv_take_pic"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="从手机相册选择"
        android:textColor="@android:color/background_dark"
        android:textSize="16sp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="6dp"
        android:background="#08000000" />

    <TextView
        android:id="@+id/tv_cancel"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="取消"
        android:textColor="@android:color/background_dark"
        android:textSize="16sp" />

</LinearLayout>

 

动画主题

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Dialog" parent="android:Theme.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">true</item>
    </style>

    <style name="main_menu_animStyle">
        <item name="android:windowEnterAnimation">@anim/dialog_in_anim</item>
        <item name="android:windowExitAnimation">@anim/dialog_out_anim</item>
    </style>
</resources>

动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:fromYDelta="1000"
        android:toXDelta="0"
        android:toYDelta="0" />
</set>

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="1000" />
</set>

 

 

完整代码

 

package com.baosight.wh.app;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import cn.hutool.core.collection.CollectionUtil;
import com.baosight.wh.app.bridge.appInfo.BSBridge;
import com.baosight.wh.app.utils.CacheUtils;
import com.baosight.wh.app.utils.ConfigUtils;
import com.baosight.wh.app.utils.FileUtil;
import wendu.dsbridge.DWebView;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
//import com.baosight.wh.app.bridge.config.BSWebView;
//import com.baosight.wh.app.bridge.config.BSWebViewClient;
//import com.baosight.wh.app.bridge.config.JSResolver;


public class MainActivity extends AppCompatActivity {

    private static final String MAIN_URL = "MAIN_URL";

    private DWebView dWebView;

    //input文件回调
    private ValueCallback<Uri[]> mFileCallback;

    @SuppressLint("StaticFieldLeak")
    public static Context context;

    //上传文件常量
    public static final int REQUEST_CODE_CAMERA = 0x4001;
    public static final int REQUEST_CODE_PICTURE = 0x4002;

    private static int MODE_OPEN_MULTIPLE = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bridge_webview);
        context = this.getApplicationContext();
        dWebView = findViewById(R.id.mainBridgeView);
        dWebView.addJavascriptObject(new BSBridge(this) , null);
            String mainUrl = ConfigUtils.getFieldBuildConfig(MAIN_URL);
        dWebView.loadUrl(mainUrl);
        //定义拍照
        dWebView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                mFileCallback = filePathCallback;
                MODE_OPEN_MULTIPLE = fileChooserParams.getMode();
                showImageSelectDialog();
                return true;
            }


        });
    }

    //自主选择相机或者相册dialog
    private boolean isClick = false;

    private void showImageSelectDialog() {
        isClick = false;
        final Dialog dialog = new Dialog(this, R.style.Dialog);
        View view = View.inflate(this, R.layout.dialog_custom_layout, null);
        dialog.setContentView(view);

        Window window = dialog.getWindow();
        window.setGravity(Gravity.BOTTOM);
        window.setWindowAnimations(R.style.main_menu_animStyle);
        window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        dialog.show();

        //打开相机按钮
        dialog.findViewById(R.id.tv_take_photo).setOnClickListener(view1 -> {
            isClick = true;
            openCamera();
            dialog.dismiss();
        });
        //打开相册按钮
        dialog.findViewById(R.id.tv_take_pic).setOnClickListener(view2 -> {
            isClick = true;
            takePhoto();
            dialog.dismiss();
        });

        //取消按钮
        dialog.findViewById(R.id.tv_cancel).setOnClickListener(view3 -> dialog.dismiss());
        //关闭dialog
        dialog.setOnDismissListener(dialog1 -> {
            if ( ! isClick ) {
                mFileCallback.onReceiveValue(null);
            }
        });
    }

    //打开相机
    private void openCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File p = Environment.getExternalStorageDirectory();
        File dir = new File(FileUtil.getImageTempPath());
        if ( ! dir.exists() ) {
            dir.mkdirs();
        }
        String picName = System.currentTimeMillis() + ".jpg";
        String appId = ConfigUtils.getFieldBuildConfig("APPLICATION_ID");
        File photoFile = new File(FileUtil.getImageTempPath() + picName);
        if ( Build.VERSION.SDK_INT >= 24 ) {
            Uri uri = FileProvider.getUriForFile(context, appId + ".fileprovider", photoFile);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        } else {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        }
        CacheUtils.getInstance().setCameraPhotoPath(this, photoFile.getAbsolutePath());
        startActivityForResult(intent, REQUEST_CODE_CAMERA);
    }

    //打开相册
    private void takePhoto() {
        //传递读取本地相册意图
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        if(MODE_OPEN_MULTIPLE == 1){
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        }
        // 判断系统中是否有处理该 Intent 的 Activity
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(Intent.createChooser(intent, "Select Picture"), REQUEST_CODE_PICTURE);
        } else {
            Toast.makeText(MainActivity.this, "未找到图片查看器", Toast.LENGTH_SHORT).show();
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {


        //input控件相关回调设置
        if ( resultCode == RESULT_OK ) {
            switch (requestCode) {
                case REQUEST_CODE_CAMERA:
                    String path = CacheUtils.getInstance().getCameraPhotoPath(this);
                    File file = new File(path);
                    if ( file.exists() ) {
                        mFileCallback.onReceiveValue(new Uri[]{Uri.fromFile(file)});
                    } else {
                        mFileCallback.onReceiveValue(null);
                    }
                    mFileCallback = null;
                    break;
                case REQUEST_CODE_PICTURE:
                    if(data != null){
                        Uri uri = data.getData();
                        List<Uri> uriList = new ArrayList<>();
                        if (uri != null) {
                            //没设置Intent.EXTRA_ALLOW_MULTIPLE,会回调这个
                            uriList.add(uri);
                        } else if (data.getClipData() != null) {
                            //设置Intent.EXTRA_ALLOW_MULTIPLE,会回调这个
                            ClipData clipData = data.getClipData();
                            int count = clipData.getItemCount();
                            if(count > 0){
                                for (int i=0; i<count; i++){
                                    Uri imageUri =clipData.getItemAt(i).getUri();
                                    uriList.add(imageUri);
                                }
                            }else {
                                Toast.makeText(context , "获取数据为空", Toast.LENGTH_LONG).show();
                            }
                        } else {
                            Toast.makeText(context , "获取数据为空", Toast.LENGTH_LONG).show();
                        }
                        if(CollectionUtil.isNotEmpty(uriList)){
                            Uri[] uris = uriList.toArray(new Uri[uriList.size()]);
                            mFileCallback.onReceiveValue(uris);
                        }
                    } else {
                        Toast.makeText(context , "获取数据为空", Toast.LENGTH_LONG).show();
                    }
                    mFileCallback = null;
                    break;
                default:
                    break;
            }
        }
        if ( mFileCallback != null ) {
            mFileCallback.onReceiveValue(null);
            mFileCallback = null;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

 

前端代码

 <div class="blue_btn" @click="upload">
      <input type="file" ref="file" accept="image/*" @change="getPic"
        multiple="multiple" style='display:none' />上传文件
 </div>
async getPic(e) {
      var that = this
      const files = e.target.files;
      console.log(files);
      for (let i = 0; i < files.length; i++) {
        that.getBase64(files[i]).then(res => {
          that.base64List.push(res);
        })
      }
    },
    upload() {
      this.$refs.file.click();
    },
    /**
      * file 转Base64 DataURL
      * @param {File} file
      * @returns
      */
    getBase64(file) {
      return new Promise((resolve, reject) => {
        ///FileReader类就是专门用来读文件的
        const reader = new FileReader()
        //开始读文件
        //readAsDataURL: dataurl它的本质就是图片的二进制数据, 进行base64加密后形成的一个字符串,
        reader.readAsDataURL(file)
        // 成功和失败返回对应的信息,reader.result一个base64,可以直接使用
        reader.onload = () => resolve(reader.result)
        // 失败返回失败的信息
        reader.onerror = error => reject(error)
      })
    },

注:如果调用相机闪退,取相册数据为空,请检查相机相册已经媒体访问的权限是否加入

标签:相册,app,相机,Intent,dialog,new,import,android,intent
From: https://www.cnblogs.com/skrr/p/17252052.html

相关文章

  • 广州APP定制开发要把握的阶段,帮你成功开发
     一些人虽然有意广州APP定制开发,但是他们在和开发商合作的时候经常会出现一些问题,导致开发失败。为此我们在开发过程中要把握一些阶段,今天名锐讯动为大家介绍广州APP定制......
  • Android Hybird架构之整合XwalkView,让你的App内置chromium内核
    使用XwalkView的目的无非是为了提升Android4.4以下版本(非chromium内核)的Html5渲染性能,并且能够使得H5页面在众多定制化的ROM上拥有一致的体验。当然了,App内置Chromuim内......
  • 如何使用ShareSDK快速实现Android APP的社会化分享登录功能
    社会化分享登录功能是许多AndroidApp开发者都需要实现的一个需求,它可以让用户通过第三方平台(如微信、QQ、微博等)进行分享和授权,提高用户体验和活跃度。但是,如果要自己集成......
  • 从零开始搞一个androidApp,实现h5自动更新、jsbridge
    准备window电脑javajdk(包含了javajre)下载安装androidsdk下载安装androidstudio下载安装gradle下载一台带sim卡的android手机nodejs下载安装 npminstall-g......
  • Uniapp最新版IOS打包详
    需要公司提供苹果开发者账号即可1.打开苹果开发者官网点击打开链接......
  • CSAPP-Shell Lab
    提供的工具:parseline:获取参数列表char**argv,返回是否为后台运行命令(true)。clearjob:清除job结构。initjobs:初始化jobs链表。maxjid:返回jobs链表中最大的jid号。ad......
  • CSAPP-Architecture Lab
    PartA前置准备gcc-Wall-O1-g-cyis.cgcc-Wall-O1-g-cisa.cgcc-Wall-O1-gyis.oisa.o-oyisgcc-Wall-O1-g-cyas.cflexyas-grammar.lexmake:fl......
  • uni-app 实现市级定位
    uni-app实现市级定位<template><viewclass=""></view></template><script>exportdefault{data(){return{};},onLoad(option){constse......
  • Cannot resolve symbol 'Mapper'
    准备写一个Mapper接口,可它报错了 上网一查,发现需要添加依赖,于是乎添加呗!<!--mybatis整合Springboot--><dependency><groupId>org.mybatis.spring.boot</gro......
  • 使用uni-app写小程序,解析含有html标签的富文本
    最近在改一个项目,将html+js+css的项目改成小程序,我说使用的uni来写的,其中遇到一个问题,就是需要解析富文本,在vue中可以直接使用v-html,但是小程序中的标签都是view,text以及i......