在APP中的那些图片上传是如何做的?PictureSelector—一个强大的图片选择器。相机和相册选择分开

简介: 在APP中的那些图片上传是如何做的?PictureSelector—一个强大的图片选择器。相机和相册选择分开

简述

PictureSelector相机和相册选择分开,全部代码,拿去可用。

流程,Android 通过webView的loadUrl一个H5页面。H5页面点击file,webview通过setWebChromeClient重写onShowFileChooser【当H5点击file时候会自动执行Android中onShowFileChooser方法】。然后后面再对点击的不同执行其他操作,是拍照、选择相册还是其他的。废话不多说,直接看gif动图和代码。

动图

这就是简单实现的内容,细节方面因为前端只能接受一张照片,所以还没有做处理。两张以及两张以上可以在前端做一个循环,因为Android中回调的是一个数组形式的。大致实现了,细节方面可以再自己优化优化。


gif动图。。。。。。

核心代码

重写onShowFileChooser

webView.setWebChromeClient(new WebChromeClient() {
            /**
             * API >= 21(Android 5.0.1)回调此方法
             */
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, WebChromeClient.FileChooserParams
                    fileChooserParams) {
                Log.e("file回调", "运行方法 onShowFileChooser");
                // (1)该方法回调时说明版本API >= 21,此时将结果赋值给 mUploadCallbackAboveL,使之 != null
                mUploadCallbackAboveL = valueCallback;
                showPopwindow();
                return true;
            }
        });

PictureSelector点击直接激活相机

 private void SelectorPhoto() {
        PictureSelector.create(this)
                .openCamera(SelectMimeType.ofImage())
                .imageEngine(GlideEngine.createGlideEngine())
                .forResult(new OnResultCallbackListener<LocalMedia>() {
                    @Override
                    public void onResult(List<LocalMedia> result) {
                        mUploadCallbackAboveL.onReceiveValue(new Uri[]{Uri.parse(result.get(0).getPath())});
                    }
                    @Override
                    public void onCancel() {
                    }
                });
    }

弹窗代码

private void showPopwindow() {
        View parent = ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
        View popView = inflate(this, R.layout.camera_pop_menu, null);
        Button btnCamera = (Button) popView.findViewById(R.id.btn_camera_pop_camera);
        Button btnAlbum = (Button) popView.findViewById(R.id.btn_camera_pop_album);
        Button btnCancel = (Button) popView.findViewById(R.id.btn_camera_pop_cancel);
        int width = getResources().getDisplayMetrics().widthPixels;
        int height = getResources().getDisplayMetrics().heightPixels;
        final PopupWindow popWindow = new PopupWindow(popView,width,height);
        popWindow.setFocusable(true);
        popWindow.setOutsideTouchable(false);// 设置同意在外点击消失
        View.OnClickListener listener = new View.OnClickListener() {
            public void onClick(View v) {
                switch (v.getId()) {
                    case R.id.btn_camera_pop_camera:
//                        takePhoto();
                        SelectorPhoto();
                        break;
                    case R.id.btn_camera_pop_album:
                        InitSelectorMethold();
                        break;
                    case R.id.btn_camera_pop_cancel:
                        break;
                }
                popWindow.dismiss();
            }
        };
        btnCamera.setOnClickListener(listener);
        btnAlbum.setOnClickListener(listener);
        btnCancel.setOnClickListener(listener);
        ColorDrawable dw = new ColorDrawable(0x30000000);
        popWindow.setBackgroundDrawable(dw);
        popWindow.showAtLocation(parent, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
    }

private String url = “http://10.1.192.88:8080/pictures.html”;

因为想要更接近项目环境,为了更好的体现出webview,所以这个是使用http-server【小型服务器(本地)】,手机和电脑要在同一个局域网下。当然你也可以不用。使用本地文件。

全部代码

MainActivity.java

package com.example.app7;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.PopupWindow;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.listener.OnResultCallbackListener;
import java.util.List;
import static android.view.View.inflate;
public class MainActivity extends AppCompatActivity {
    private Uri imageUri;
    private int REQUEST_CODE = 1234;
    private android.webkit.ValueCallback<Uri[]> mUploadCallbackAboveL;
    private android.webkit.ValueCallback<Uri> mUploadCallbackBelow;
    private WebView webView;
    private String url = "http://10.1.192.88:8080/pictures.html";
    //  todo   private AlertDialog.Builder PictureSelector;
    private Object PictureMimeType;
    private com.luck.picture.lib.config.PictureMimeType SelectMimeType;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initWebView();
    }
    //初始化webView
    private void initWebView() {
        //从布局文件中扩展webView
        webView = (WebView) this.findViewById(R.id.webview);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            webView.setWebContentsDebuggingEnabled(true);
        }
        initWebViewSetting();
    }
    //初始化webViewSetting
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    private void initWebViewSetting() {
        WebSettings settings = webView.getSettings();
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);
        settings.setDomStorageEnabled(true);
        settings.setDefaultTextEncodingName("UTF-8");
        settings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true
        settings.setAllowFileAccess(true);    // 是否可访问本地文件,默认值 true
        // 是否允许通过file url加载的Javascript读取本地文件,默认值 false
        settings.setAllowFileAccessFromFileURLs(false);
        // 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false
        settings.setAllowUniversalAccessFromFileURLs(false);
        //开启JavaScript支持
        settings.setJavaScriptEnabled(true);
        // 支持缩放
        settings.setSupportZoom(true);
        //加载地址
        webView.loadUrl(url);
        webView.setWebChromeClient(new WebChromeClient() {
            /**
             * API >= 21(Android 5.0.1)回调此方法
             */
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, WebChromeClient.FileChooserParams
                    fileChooserParams) {
                Log.e("file回调", "运行方法 onShowFileChooser");
                // (1)该方法回调时说明版本API >= 21,此时将结果赋值给 mUploadCallbackAboveL,使之 != null
                mUploadCallbackAboveL = valueCallback;
//                InitSelectorMethold();
//                takePhoto();
//                AlertDialog.Builder dialog=new AlertDialog.Builder(MainActivity.this);
//                dialog.setTitle("这是一个弹框提示");
//                dialog.setMessage("嗯,这是消息内容");
//                dialog.setCancelable(false);
//
//                dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
//                    @Override
//                    public void onClick(DialogInterface dialogInterface, int i) {
//                        Toast.makeText(MainActivity.this, "确定,成功了", Toast.LENGTH_SHORT).show();
//                        InitSelectorMethold();
//                    }
//
//
//                });
//                dialog.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
//                    @Override
//                    public void onClick(DialogInterface dialogInterface, int i) {
//                        Toast.makeText(MainActivity.this,"取消,失败了",Toast.LENGTH_SHORT).show();
//                        takePhoto();
//
//                    }
//
//
//                });
//
//                dialog.show();
                showPopwindow();
                return true;
            }
        });
    }
    private void showPopwindow() {
        View parent = ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
        View popView = inflate(this, R.layout.camera_pop_menu, null);
        Button btnCamera = (Button) popView.findViewById(R.id.btn_camera_pop_camera);
        Button btnAlbum = (Button) popView.findViewById(R.id.btn_camera_pop_album);
        Button btnCancel = (Button) popView.findViewById(R.id.btn_camera_pop_cancel);
        int width = getResources().getDisplayMetrics().widthPixels;
        int height = getResources().getDisplayMetrics().heightPixels;
        final PopupWindow popWindow = new PopupWindow(popView,width,height);
        popWindow.setFocusable(true);
        popWindow.setOutsideTouchable(false);// 设置同意在外点击消失
        View.OnClickListener listener = new View.OnClickListener() {
            public void onClick(View v) {
                switch (v.getId()) {
                    case R.id.btn_camera_pop_camera:
//                        takePhoto();
                        SelectorPhoto();
                        break;
                    case R.id.btn_camera_pop_album:
                        InitSelectorMethold();
                        break;
                    case R.id.btn_camera_pop_cancel:
                        break;
                }
                popWindow.dismiss();
            }
        };
        btnCamera.setOnClickListener(listener);
        btnAlbum.setOnClickListener(listener);
        btnCancel.setOnClickListener(listener);
        ColorDrawable dw = new ColorDrawable(0x30000000);
        popWindow.setBackgroundDrawable(dw);
        popWindow.showAtLocation(parent, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
    }
    private void SelectorPhoto() {
        PictureSelector.create(this)
                .openCamera(SelectMimeType.ofImage())
                .imageEngine(GlideEngine.createGlideEngine())
                .forResult(new OnResultCallbackListener<LocalMedia>() {
                    @Override
                    public void onResult(List<LocalMedia> result) {
                        mUploadCallbackAboveL.onReceiveValue(new Uri[]{Uri.parse(result.get(0).getPath())});
                    }
                    @Override
                    public void onCancel() {
                    }
                });
    }
    private void InitSelectorMethold() {
        // 进入相册 以下是例子:用不到的api可以不写
        PictureSelector.create(this)
                .openGallery(PictureConfig.TYPE_IMAGE)//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
//                .theme()//主题样式(不设置为默认样式) 也可参考demo values/styles下 例如:R.style.picture.white.style
                .maxSelectNum(4)// 最大图片选择数量 int
                .minSelectNum(2)// 最小选择数量 int
//                .imageSpanCount(4)// 每行显示个数 int
                .selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
                .previewImage(true)// 是否可预览图片 true or false
                .previewVideo(true)// 是否可预览视频 true or false
                .enablePreviewAudio(true) // 是否可播放音频 true or false
//                .isCamera(true)// 是否显示拍照按钮 true or false
//                .imageFormat(PictureMimeType.PNG)// 拍照保存图片格式后缀,默认jpeg
                .isZoomAnim(true)// 图片列表点击 缩放效果 默认true
                .sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效
                .setOutputCameraPath("/CustomPath")// 自定义拍照保存路径,可不填
                .enableCrop(true)// 是否裁剪 true or false
                .compress(true)// 是否压缩 true or false
                .glideOverride(100, 100)// int glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
                .withAspectRatio(1, 1)// int 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
                .hideBottomControls(true)// 是否显示uCrop工具栏,默认不显示 true or false
                .isGif(true)// 是否显示gif图片 true or false
                .freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
//                .circleDimmedLayer()// 是否圆形裁剪 true or false
//                .showCropFrame()// 是否显示裁剪矩形边框 圆形裁剪时建议设为false   true or false
//                .showCropGrid()// 是否显示裁剪矩形网格 圆形裁剪时建议设为false    true or false
//                .openClickSound()// 是否开启点击声音 true or false
//                .selectionMedia()// 是否传入已选图片 List<LocalMedia> list
//                .previewEggs()// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) true or false
//                .cropCompressQuality()// 裁剪压缩质量 默认90 int
                .minimumCompressSize(10)// 小于100kb的图片不压缩
                .synOrAsy(true)//同步true或异步false 压缩 默认同步
//                .cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 int
//                .rotateEnabled() // 裁剪是否可旋转图片 true or false
//                .scaleEnabled()// 裁剪是否可放大缩小图片 true or false
//                .videoQuality()// 视频录制质量 0 or 1 int
                .videoMaxSecond(15)// 显示多少秒以内的视频or音频也可适用 int
                .videoMinSecond(10)// 显示多少秒以内的视频or音频也可适用 int
//                .recordVideoSecond()//视频秒数录制 默认60s int
                .isDragFrame(false)// 是否可拖动裁剪框(固定)
                .imageEngine(GlideEngine.createGlideEngine())
                .forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case PictureConfig.CHOOSE_REQUEST:
                    // 结果回调
                    List<LocalMedia> selectList = PictureSelector.obtainMultipleResult(data);
//
//                    for (int i = 0; i < 2; i++) {
//                        Uri urt = Uri.parse(selectList.get(i).getPath());
//
//                        Log.e("这是一个循环测试,看看数据什么样的", "onActivityResult: "+urt);
//                    }
                    mUploadCallbackAboveL.onReceiveValue(new Uri[]{Uri.parse(selectList.get(0).getPath())});
                    break;
                default:
                    break;
            }
        }
    }
}

GlideEngine.java

package com.example.app7;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.bumptech.glide.request.target.ImageViewTarget;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.listener.OnImageCompleteCallback;
import com.luck.picture.lib.tools.MediaUtils;
import com.luck.picture.lib.widget.longimage.ImageSource;
import com.luck.picture.lib.widget.longimage.ImageViewState;
import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView;
public class GlideEngine implements ImageEngine {
    /**
     * 加载图片
     *
     * @param context
     * @param url
     * @param imageView
     */
    @Override
    public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
        Glide.with(context)
                .load(url)
                .into(imageView);
    }
    /**
     * 加载网络图片适配长图方案
     * # 注意:此方法只有加载网络图片才会回调
     *
     * @param context
     * @param url
     * @param imageView
     * @param longImageView
     * @param callback      网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
     */
    @Override
    public void loadImage(@NonNull Context context, @NonNull String url,
                          @NonNull ImageView imageView,
                          SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) {
        Glide.with(context)
                .asBitmap()
                .load(url)
                .into(new ImageViewTarget<Bitmap>(imageView) {
                    @Override
                    public void onLoadStarted(@Nullable Drawable placeholder) {
                        super.onLoadStarted(placeholder);
                        if (callback != null) {
                            callback.onShowLoading();
                        }
                    }
                    @Override
                    public void onLoadFailed(@Nullable Drawable errorDrawable) {
                        super.onLoadFailed(errorDrawable);
                        if (callback != null) {
                            callback.onHideLoading();
                        }
                    }
                    @Override
                    protected void setResource(@Nullable Bitmap resource) {
                        if (callback != null) {
                            callback.onHideLoading();
                        }
                        if (resource != null) {
                            boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
                                    resource.getHeight());
                            longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
                            imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
                            if (eqLongImage) {
                                // 加载长图
                                longImageView.setQuickScaleEnabled(true);
                                longImageView.setZoomEnabled(true);
                                longImageView.setPanEnabled(true);
                                longImageView.setDoubleTapZoomDuration(100);
                                longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
                                longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
                                longImageView.setImage(ImageSource.bitmap(resource),
                                        new ImageViewState(0, new PointF(0, 0), 0));
                            } else {
                                // 普通图片
                                imageView.setImageBitmap(resource);
                            }
                        }
                    }
                });
    }
    /**
     * 加载网络图片适配长图方案
     * # 注意:此方法只有加载网络图片才会回调
     *
     * @param context
     * @param url
     * @param imageView
     * @param longImageView
     * @ 已废弃
     */
    @Override
    public void loadImage(@NonNull Context context, @NonNull String url,
                          @NonNull ImageView imageView,
                          SubsamplingScaleImageView longImageView) {
        Glide.with(context)
                .asBitmap()
                .load(url)
                .into(new ImageViewTarget<Bitmap>(imageView) {
                    @Override
                    protected void setResource(@Nullable Bitmap resource) {
                        if (resource != null) {
                            boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
                                    resource.getHeight());
                            longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
                            imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
                            if (eqLongImage) {
                                // 加载长图
                                longImageView.setQuickScaleEnabled(true);
                                longImageView.setZoomEnabled(true);
                                longImageView.setPanEnabled(true);
                                longImageView.setDoubleTapZoomDuration(100);
                                longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
                                longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
                                longImageView.setImage(ImageSource.bitmap(resource),
                                        new ImageViewState(0, new PointF(0, 0), 0));
                            } else {
                                // 普通图片
                                imageView.setImageBitmap(resource);
                            }
                        }
                    }
                });
    }
    /**
     * 加载相册目录
     *
     * @param context   上下文
     * @param url       图片路径
     * @param imageView 承载图片ImageView
     */
    @Override
    public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
        Glide.with(context)
                .asBitmap()
                .load(url)
                .override(180, 180)
                .centerCrop()
                .sizeMultiplier(0.5f)
                .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
                .into(new BitmapImageViewTarget(imageView) {
                    @Override
                    protected void setResource(Bitmap resource) {
                        RoundedBitmapDrawable circularBitmapDrawable =
                                RoundedBitmapDrawableFactory.
                                        create(context.getResources(), resource);
                        circularBitmapDrawable.setCornerRadius(8);
                        imageView.setImageDrawable(circularBitmapDrawable);
                    }
                });
    }
    /**
     * 加载gif
     *
     * @param context   上下文
     * @param url       图片路径
     * @param imageView 承载图片ImageView
     */
    @Override
    public void loadAsGifImage(@NonNull Context context, @NonNull String url,
                               @NonNull ImageView imageView) {
        Glide.with(context)
                .asGif()
                .load(url)
                .into(imageView);
    }
    /**
     * 加载图片列表图片
     *
     * @param context   上下文
     * @param url       图片路径
     * @param imageView 承载图片ImageView
     */
    @Override
    public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
        Glide.with(context)
                .load(url)
                .override(200, 200)
                .centerCrop()
                .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
                .into(imageView);
    }
    private GlideEngine() {
    }
    private static GlideEngine instance;
    public static GlideEngine createGlideEngine() {
        if (null == instance) {
            synchronized (GlideEngine.class) {
                if (null == instance) {
                    instance = new GlideEngine();
                }
            }
        }
        return instance;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/mPictre"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </WebView>
</LinearLayout>

camera_pop_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_margin="10dp"
    android:orientation="vertical" >
    <Button
        android:text="拍照"
        android:id="@+id/btn_camera_pop_camera"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:textSize="18sp" />
    <Button
        android:text="选相册"
        android:id="@+id/btn_camera_pop_album"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:textSize="18sp" />
    <Button
        android:text="选文件"
        android:id="@+id/btn_camera_pop_cancel"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_marginTop="10dp"
        android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.app7">
    <!-- 联网权限开启 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission
        android:name="android.permission.WRITE_MEDIA_STORAGE"
        tools:ignore="ProtectedPermissions" />
    <uses-permission
        android:name="android.permission.WRITE_SETTINGS"
        tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <queries package="${applicationId}">
        <intent>
            <action android:name="android.media.action.IMAGE_CAPTURE"></action>
        </intent>
        <intent>
            <action android:name="android.media.action.ACTION_VIDEO_CAPTURE"></action>
        </intent>
    </queries>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.WebViewClient"
        android:usesCleartextTraffic="true">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

除了上面的之外,PictureSelector还有很多方法,例如下面的部分微信图片_20220927123505.png

目录
相关文章
|
4月前
|
XML Java Android开发
Android Studio App开发之使用相机拍摄照片和从相册中选取图片(附源码 超详细必看)
Android Studio App开发之使用相机拍摄照片和从相册中选取图片(附源码 超详细必看)
175 0
|
XML 移动开发 小程序
抖音小程序开发 唤起收银台支付(可以选择支付宝APP支付或微信H5支付)
字节跳动也开放了小程序给商家接入,可以在旗下APP如抖音、今日头条、今日头条极速版等应用中即点即用,基于庞大的数亿用户量为其引流,帮助商家获取用户流量,销售商品,其模式和微信小程序差不多。
1750 0
抖音小程序开发 唤起收银台支付(可以选择支付宝APP支付或微信H5支付)
|
2月前
|
移动开发 小程序 API
【7月开发者日回顾】小程序回跳APP链路、相机组件等多个新能力计划公布!
【7月开发者日回顾】小程序回跳APP链路、相机组件等多个新能力计划公布!
35 2
|
4月前
|
XML vr&ar Android开发
【Android App】实战项目之虚拟现实(VR)的全景相册(附源码和演示视频 可用于学习和大作业)
【Android App】实战项目之虚拟现实(VR)的全景相册(附源码和演示视频 可用于学习和大作业)
148 2
|
XML Java Android开发
【安卓开发】调用手机的相机进行拍照并且保存在本地的APP
【安卓开发】调用手机的相机进行拍照并且保存在本地的APP
247 0
|
负载均衡 算法
短视频开发app,选择正确的负载均衡算法很重要
短视频开发app,选择正确的负载均衡算法很重要
|
移动开发 人工智能 安全
谈到App加固,裕信银行选择顶象
移动互联网时代,App已经成为了商业银行触达和经营客户的主要阵地.
81 0
谈到App加固,裕信银行选择顶象
选择语音聊天app源码,重点考察对象有哪些?
选择语音聊天app源码,重点考察对象有哪些?
|
数据安全/隐私保护
短视频app开发,做好功能选择让开发事半功倍
短视频app开发,做好功能选择让开发事半功倍
小孩子才做选择!这款APP让你免费无限畅享高质量阅读
前不久,一个偶然的机会听了一段关于马尔克斯《百年孤独》的介绍。突然,勾起我强烈想要看这本早有耳闻的知名书籍。
小孩子才做选择!这款APP让你免费无限畅享高质量阅读