android之实现打开相册、拍照录像、播放视频、保存图片到系统相册\指定位置、图片压缩[通俗易懂]

android之实现打开相册、拍照录像、播放视频、保存图片到系统相册\指定位置、图片压缩[通俗易懂]———照相录像——//实现照相、录像的功能publicvoidcameraForphoto(){Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);Filefile=newFile(Environment.getExternalStorageDirecto…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

打开相册选择图片裁剪:https://blog.csdn.net/Code_legend/article/details/77620359

https://blog.csdn.net/zz110753/article/details/60877594

图片选择框架:星级最多https://github.com/LuckSiege/PictureSelector

https://github.com/wildma/PictureSelector

https://github.com/HuanTanSheng/EasyPhotos

 

自定义的一些请求码:

private static final int CODE_GALLERY_REQUEST = 0xa0;
private static final int CODE_CAMERA_REQUEST = 0xa1;
private static final int CODE_RESULT_REQUEST = 0xa2;
private static final int CAMERA_PERMISSIONS_REQUEST_CODE = 0x03;
private static final int STORAGE_PERMISSIONS_REQUEST_CODE = 0x04;
private static final int CHOOSE_PHOTO = 0x05;

检查权限、动态请求权限、权限回调

 /**
     * 动态申请sdcard读写权限
     */
    private void autoObtainStoragePermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE);
            } else {

            }
        } else {

        }
    }

    /**自Android 6.0以后对某些涉及用户隐私权限的获取需要动态获取,所以首先是检查权限,如没有权限则动态申请权限,这里我们需要用到的权限是WRITE_EXTERNAL_STORAGE和CAMERA。

    * FileProvider是ContentProvider的一个子类,用于应用程序之间私有文件的传递。自Android 7.0后系统禁止应用向外部公开file://URI ,
     * 因此需要FileProvider来向外界传递URI,传递的形式是content : //Uri,使用时需要在清单文件中注册。
     *
     *
     * 申请访问相机权限
     */
    private void autoObtainCameraPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkPermission()) {//检查权限
                //没有权限,发送权限请求
                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA)) {
                    Toast.makeText(getActivity(), "您已经拒绝过一次了", Toast.LENGTH_SHORT).show();
                }
                //请求相机权限
                requestPermissions();

            } else {//有权限直接调用系统相机拍照
                if (hasSdcard()) {//sd卡挂载上了,可读可写
                    //打开相机
    
                } else {

                    Toast.makeText(getActivity(), "没有SD卡", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    //检查权限
    private boolean checkPermission() {
        //是否有权限
        boolean haveCameraPermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;

        boolean haveWritePermission = ContextCompat.checkSelfPermission(getActivity(),
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;

        return haveCameraPermission && haveWritePermission;
    }

    // 请求相机权限和sd卡权限
    @RequiresApi(api = Build.VERSION_CODES.M)
    private void requestPermissions() {
        requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_PERMISSIONS_REQUEST_CODE);
    }

    //请求权限的回调
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        Log.d(TAG, "onRequestPermissionsResult: ");
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            //调用系统相机申请拍照权限回调
            case CAMERA_PERMISSIONS_REQUEST_CODE: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//允许授权
                    if (hasSdcard()) {
//拍照
                    } else {
                        Toast.makeText(getActivity(), "没有SD卡", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(getActivity(), "请允许打开相机", Toast.LENGTH_SHORT).show();
                }
                break;
            }
            //调用系统相册申请Sdcard权限回调
            case STORAGE_PERMISSIONS_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//打开相册
                } else {
                    Toast.makeText(getActivity(), "请允许操作SD卡", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }


    /**
     * 检查设备是否存在SDCard的工具方法
     */
    public static boolean hasSdcard() {
        String state = Environment.getExternalStorageState();
        return state.equals(Environment.MEDIA_MOUNTED);
    }

拍照

系统相机拍照:

1.//定义一个保存图片的File变量 private File currentImageFile = null; private Uri currentImageUri=null;

/**
 *
 * 自己定义一个保存路径,(拍完的图片是不会保存到本地的, 我们可以自己写代码把图片保存到我们的SD卡里,然后再显示,这样的图片会清晰很多.)
 * */

public void createSavepath(){
    File dir = new File(Environment.getExternalStorageDirectory(),"pictures");
    if(!dir.exists()){
        dir.mkdirs();
    }
    currentImageFile = new File(dir,System.currentTimeMillis() + ".jpg");
    if(!currentImageFile.exists()){
        try {
            currentImageFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    Log.d("extra",""+dir.toString());
}

2.在res下面创建一个xml文件夹,xml下面建立file_paths.xml文件,这个文件的主要作用是向外提供content://uri路径。

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--files-path  相当于 getFilesDir()-->
    <files-path name="my_images" path="images"/>
    <!--cache-path  相当于 getCacheDir()-->
    <cache-path name="lalala" path="cache_image"/>
    <!--external-path  相当于 Environment.getExternalStorageDirectory()-->
    <external-path  name="hahaha" path="."/>
    <!--external-files-path  相当于 getExternalFilesDir("") -->
    <external-files-path name="paly" path="freeSoft"/>
    <!--external-cache-path  相当于 getExternalCacheDir() -->
    <external-cache-path  name="lei" path="."/>

</paths>

3.manifest配置:application下面添加provide配置

<application>
  <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.wofu.aichi010.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

权限:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

4.打开相机,需要动态添加权限

方法一:这种方法是自定义路径存储图片
       createSavepath();//上面自定义保存路径
       currentImageUri =  FileProvider.getUriForFile(getActivity(), "com.example.wofu.aichi010.fileprovider" ,currentImageFile);
      //打开相机
       Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
           it.putExtra(MediaStore.EXTRA_OUTPUT,currentImageUri);//输出到指定路径
       it.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);//授予临时权限

       startActivityForResult(it, Activity.DEFAULT_KEYS_DIALER);

 

方法二:这种方法不存储图片,

Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(it,Activity.DEFAULT_KEYS_DIALER);

 

5.回调获取图片

 //重写onActivityResult方法,相机拍照后会返回一个intent给onActivityResult。 intent的extra部分包含一个编码过的Bitmap,
 // 拍完的图片是不会保存到本地的, 我们可以自己写代码把图片保存到我们的SD卡里,然后再显示,这样的图片会清晰很多.
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
   Log.d("回调图片","照片"+resultCode+data+requestCode);
     if (resultCode == Activity.RESULT_OK) {
方式一:自定义路径中获取图片
img_show.setImageURI(currentImageUri);

方式二:直接使用图片,不存储,img_show是Imageview
         Bundle bundle = data.getExtras();
         Bitmap bitmap = (Bitmap) bundle.get("data");
        img_show.setImageBitmap(bitmap);
     }
 }

 

 

自定义相机拍照:

 

 

 

保存图片

—————保存图片到指定位置———

 

将Bitmap保存图片到指定的路径/sdcard/Boohee/下,文件名以当前系统时间命名,但是这种方法保存的图片没有加入到系统图库中

public static File saveImage(Bitmap bmp) {
    File appDir = new File(Environment.getExternalStorageDirectory(), "Boohee");
    if (!appDir.exists()) {
        appDir.mkdir();
    }
    String fileName = System.currentTimeMillis() + ".jpg";
    File file = new File(appDir, fileName);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        bmp.compress(CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

———————保存图片到系统相册——-

调用以上系统自带的方法会把bitmap对象保存到系统图库中, 但是这种方法无法指定保存的路径和名称, 上述方法的title、description参数只是插入数据库中的字段, 真实的图片名称系统会自动分配。插入图库的方法图片并没有立刻显示在图库中,而我们需要立刻更新系统图库以便让用户可以立刻查看到这张图片。

MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), bitmap, “title”, “description”);

 

录像

1.创建路线个保存路径:

//定义一个保存视频的File变量
private File currentImageFile = null;
private Uri currentImageUri=null;
public void createvideoSavepath(){
    File dir = new File(Environment.getExternalStorageDirectory(),"videos");
    if(!dir.exists()){
        dir.mkdirs();
    }
    currentImageFile = new File(dir,System.currentTimeMillis() + ".mp4");
    if(!currentImageFile.exists()){
        try {
            currentImageFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    Log.d("extra",""+dir.toString());
}

2.打开相机录像,fileprovide的配置参考相机拍照

createvideoSavepath();
currentImageUri =  FileProvider.getUriForFile(getActivity(), "com.example.wofu.aichi010.fileprovider" ,currentImageFile);
Intent intents = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intents.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intents.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri);
startActivityForResult(intents, 10);

3.录像后回调

public void onActivityResult(int requestCode, int resultCode, Intent data) {
  Log.d("回调图片","照片"+resultCode+data+requestCode);
    if (resultCode == Activity.RESULT_OK) {

}

 

 

打开相册

***从相册选择video

 

/**
 * 从相册中选择视频
 */
private void choiceVideo() {
        Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(i, 66);
        }
       
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 66 && resultCode == RESULT_OK && null != data) {
        Uri selectedVideo = data.getData();
        String[] filePathColumn = {MediaStore.Video.Media.DATA};

        Cursor cursor = getContentResolver().query(selectedVideo,
        filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        VIDEOPATH = cursor.getString(columnIndex);
        cursor.close();
        //根据时间路径播放视频       
        }
        if (resultCode != Activity.RESULT_OK) {
        return;
        }
        }

 

*****打开相册

方式一:这种方式会打开,页面显示错误报告、图库、文件管理,近期的图片页面,图片、视频、文件都可以选择

Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_PHOTO); // 打开相册

 

方式二:打开选择图片,显示的是一个个图片文件夹

Intent intentFromGallery = new Intent();
// 设置文件类型
intentFromGallery.setType("image/*");
intentFromGallery.setAction(Intent.ACTION_PICK);
startActivityForResult(intentFromGallery, CODE_GALLERY_REQUEST);

打开相册的回调:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
  Log.d("回调图片","照片"+resultCode+data+requestCode);
    if (resultCode == Activity.RESULT_OK) {
   
   

//获取Bitmap,然后加载图片

Uri uri = data.getData();
ContentResolver resolver = getActivity().getContentResolver();
try {
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(resolver,
            uri);
    img_show.setImageBitmap(bitmap);
} catch (IOException e) {
    e.printStackTrace();
}

//获取一些图片信
//Uri uri = data.getData();
//Cursor cursor =getActivity().getContentResolver().query(uri, null, null, null,null);
//if (cursor != null && cursor.moveToFirst()) {
    //这里开始查询每一列的信息,有6列
  //  String path = cursor.getString(1);//0是内存地址,1是图片格式,如image/jpeg
  //  Log.d("相册选择",path);
   // cursor.close();
//}
}

 

压缩图片

调用:

  try {
          Bitmap  bitmap  =   getBitmapFormUri(currentImageUri);
             img_show.setImageBitmap(bitmap);
         } catch (IOException e) {
             e.printStackTrace();
         }
 //缩放图片
    public Bitmap getBitmapFormUri(Uri uri) throws FileNotFoundException, IOException {
        InputStream input = getContext().getContentResolver().openInputStream(uri);

        //这一段代码是不加载文件到内存中也得到bitmap的真是宽高,主要是设置inJustDecodeBounds为true
        BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
        onlyBoundsOptions.inJustDecodeBounds = true;//不加载到内存
        onlyBoundsOptions.inDither = true;//optional
        onlyBoundsOptions.inPreferredConfig = Bitmap.Config.RGB_565;//optional
        BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
        input.close();
        int originalWidth = onlyBoundsOptions.outWidth;
        int originalHeight = onlyBoundsOptions.outHeight;
        if ((originalWidth == -1) || (originalHeight == -1))
            return null;

        //图片分辨率以480x800为标准
        float hh = 800f;//这里设置高度为800f
        float ww = 480f;//这里设置宽度为480f
        //缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        int be = 1;//be=1表示不缩放
        if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放
            be = (int) (originalWidth / ww);
        } else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放
            be = (int) (originalHeight / hh);
        }
        if (be <= 0)
            be = 1;
        //比例压缩
        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
        bitmapOptions.inSampleSize = be;//设置缩放比例
        bitmapOptions.inDither = true;
        bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        input = getActivity().getContentResolver().openInputStream(uri);
        Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
        input.close();

        return compressImage(bitmap);//再进行质量压缩
    }

    //压缩图片质量
    public Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();//重置baos即清空baos
            //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差  ,第三个参数:保存压缩后的数据的流
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options,把压缩后的数据存放到baos中
            options -= 10;//每次都减少10
            if (options<=0)
                break;
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
    }

 

—————播放视频—————–

public class MainActivity extends AppCompatActivity {

    private MediaPlayer mediaPlayer;
    private SurfaceView sfv;
    private VideoView vv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        sfv = findViewById(R.id.sfv);//可以在子线程直接更新UI


    //播放视频
    public  void play(){

        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource("http://badu.com/ddd");//要播放的数据
        } catch (IOException e) {
            e.printStackTrace();
        }
        mediaPlayer.prepareAsync();//准备播放
        //设置显示
        final SurfaceHolder holder=sfv.getHolder();
        holder.addCallback(new SurfaceHolder.Callback() {

            private int cur;

            //sfv准备好了
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                mediaPlayer.setDisplay(holder);
                //准备完成再开始播放
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        mediaPlayer.start();
                        mediaPlayer.seekTo(cur);//上次的位置
                    }
                });

            }
//变化的时候
            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

            }
//sfv销毁的时候
            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

                if(mediaPlayer!=null && mediaPlayer.isPlaying()) {
                    //获取视频当前位置
                    cur = mediaPlayer.getCurrentPosition();
                    mediaPlayer.stop();//停止
                }
            }
        });

    }


    //方法二:videoview实现视频播放
    public  void videoViewPlay(){
//videoView控件就是对surfaceView的封装,实现mediaplayer接口
        vv = findViewById(R.id.videoV);

vv.setVideoPath("http://bas.com/ee.mp4");//播放的资源
vv.start();//开始播放

    }


    //方法三:vitamio框架实现视频播放
    public  void vitamioMobviePlay(){


    }

   
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/192730.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • SAP License:实例讲解SAP与金税接口

    SAP License:实例讲解SAP与金税接口SAP与金税接口的问题很多人问我。今天我通过实例给大家讲解一下。步骤一:与金税公司取得联系,他们会给一个Word文档,里面描述金税系统的字段描述。步骤二:与金税公司签订合同,取得接口安装程序,现在有EXCEL接口和文本接口两种,建议购买EXcel接口,同时金税公司会提供U盘加密卡。步骤三:在SAP系统中做如下配置:销售和分销-基本功能-输出控制-输出确定-使用条件技术的输出确认-维护开票单据的输出确定-维护输出类型VV31双击行项目设置打印机(图片插入不进来)步骤四:Abap开发程序。

  • BI_开发_问题:ORA-26002: Table DWH.W_XACT_TYPE_D has index defined upon it.

    BI_开发_问题:ORA-26002: Table DWH.W_XACT_TYPE_D has index defined upon it.

  • ScreenToGIF录像没有声音_录屏怎么变成gif

    ScreenToGIF录像没有声音_录屏怎么变成gif剪辑视频没有高清素材,视频下载受限,大部分录屏软件难用还要收费其实电脑录屏没那么麻烦,补充更新:今天意外地发现了两款非常不错的电脑录屏软件,整个软件体积小巧、操作简单,最为难得的是,录制的视频内容特别清晰,这里推荐给大家吧。软件全称:嗨格式录屏大师(下面是体验链接,大家可以试一试)http://dl-next.aunbox.cn/channel?channel=6aef2262​dl-next.a…

  • 诺基亚被黑莓给告了,原来“专利恶霸”也在侵别人的权

    诺基亚被黑莓给告了,原来“专利恶霸”也在侵别人的权

  • iis无法启动万维网发布服务W3SVC「建议收藏」

    iis无法启动万维网发布服务W3SVC「建议收藏」启动iis时提示无法启动万维网发布服务W3SVC,方法:Win+R,输入service.msc,找到WindowsProcessActivationService服务,将该服务启动;再找到WorldWideWebPublishingService服务,将该服务改为启动,如果提示“错误1068:依赖服务或组无法启动”,就尝试这两种方法:1、打开控制面板,程序,程序和功能,启用或关闭windows功能,找到windowsprocessactivationservice,全部勾选,重启电

  • Ubuntu18.04安装Ros(最新最详细亲测)「建议收藏」

    Ubuntu18.04安装Ros(最新最详细亲测)「建议收藏」跟我一步一步来,带你轻松安装ROS

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号