iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >【Android入门到项目实战-- 7.3】—— 如何调用手机摄像头和相册
  • 759
分享到

【Android入门到项目实战-- 7.3】—— 如何调用手机摄像头和相册

智能手机androidandroidstudio开发语言 2023-08-31 05:08:44 759人浏览 独家记忆
摘要

目录 一、调用摄像头拍照 二、打开相册选择照片         学完本篇文章可以收获如何调用手机的摄像头和打开手机相册选择图片功能。 一、调用摄像头拍照 先新建一个CameraAlbumTest项目。 修改activity_main.x

目录

一、调用摄像头拍照

二、打开相册选择照片


        学完本篇文章可以收获如何调用手机的摄像头和打开手机相册选择图片功能。

一、调用摄像头拍照

先新建一个CameraAlbumTest项目

修改activity_main.xml,代码如下:

        按钮打开摄像头,ImageView将拍到的图片显示出来。

    

下面编写调用摄像头的具体逻辑,修改MainActivity代码,如下:

        按钮点击事件里首先创建一个File对象,用于存放摄像头拍下的照片,并命名为output_image.jpg,并将它存放在手机SD卡的应用关联缓存目录下(SD卡中专门存放当前应用缓存数据的位置),调用getExternalCacheDir()方法可以得到这个目录,目录具体路径是:/sdcard/Android/data/包名/cache。

        放入缓存目录下的目的是可以不需要处理运行时权限。

        接着进行一个判断,如果Android版本低于7.0,调用Uri的fromFile()方法将File对象转换成Uri对象。否则,将File对象转换为Uri对象,Uri对象标识着output_image.jpg这张图片的本地真实路径。这里使用FileProvider的getUriForFile()方法转换为Uri对象,此方法有3个参数,第一个是Context对象,第二个是任意唯一的字符串,第三个是刚刚创建的File对象。

        之所以进行转换,是因为直接使用本地真实路径Uri被认为是不安全的,会抛出异常,而FileProvider是一种特殊的内容提供器,它使用了和内容提供其类似的机制来对数据进行保护,可以选择性将封装过的Uri共享给外部,提高了安全性。

        接下来构建Intent对象,调用putExtra()方法指定图片的输出地址,这里填入的是刚刚得到的Uri对象,最后调用startActivityForResult()来启动活动,拍下的照片输出到output_image.jpg中。

        由于使用的是startActivityForResult()来启动活动,因此拍完照后结果会返回到onActivityResult()方法中,就可以调用BitmapFactory的decodeStream()方法将照片解析成Bitmap对象,然后设置到ImageView中显示出来。

public class MainActivity extends AppCompatActivity {    public static final int TAKE_PHOTO = 1;    private ImageView picture;    private Uri imageUri;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button takePhoto = (Button) findViewById(R.id.take_photo);        picture = (ImageView) findViewById(R.id.picture);        takePhoto.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {//                创建File对象,用于存储拍照后的照片                File outputImage = new File(getExternalCacheDir(),"output_image.jpg");                try {                    if(outputImage.exists()){                        outputImage.delete();                    }                    outputImage.createNewFile();                }catch (IOException e){                    e.printStackTrace();                }                if(Build.VERSION.SDK_INT >= 24){                    imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraalbumtest.fileprovider",outputImage);                }else{                    imageUri = Uri.fromFile(outputImage);                }//                启动相机                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");                intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);                startActivityForResult(intent,TAKE_PHOTO);            }        });    }    protected void onActivityResult(int requestCode,int resultCode,Intent data) {        super.onActivityResult(requestCode, resultCode, data);        switch (requestCode) {            case TAKE_PHOTO:                if (resultCode == RESULT_OK) {                    try {//                        显示拍摄的照片                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));                        picture.setImageBitmap(bitmap);                    } catch (FileNotFoundException e) {                        e.printStackTrace();                    }                }                break;            default:                break;        }    }}

然后在res目录下新建一个名字为xml的目录(如果有则忽略这步),右键xml目录 -> New -> File,创建一个file_paths.xml文件,修改内容,代码如下:

        external-path用来指定Uri共享,name属性值随意填,path属性的值表示共享的具体路径,这里设置空值表示将整个SD卡共享,也可以仅共享我们存放output_image.jpg这张图片的途径。

    

最后修改AndroidManifest.xml文件代码,如下:

        由于刚才使用了内容提供器,所以需要进行注册。

        需要声明访问SD卡的权限。

        android:name值是固定的,android:authorities的值必须要和刚才的FileProvider.getUriForFile()方法中的第二个参数的值一致,指定Uri的共享路径。

                        ...................

效果如下:

二、打开相册选择照片

        在以上项目的基础上进行修改。

        修改activity_main.xml文件,在布局中添加一个按钮用于从相册中选择照片,如下:

................... 

        修改MainActivity代码,如下:

        代码稍微有点长,因为对Android4.4以上和以下版本分别做了处理,如果你的应用不希望版本低的使用,那么可以不用处理4.4以下版本。

public class MainActivity extends AppCompatActivity {    public static final int TAKE_PHOTO = 1;    private ImageView picture;    private Uri imageUri;    public static final int CHOOSE_PHOTO = 2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button takePhoto = (Button) findViewById(R.id.take_photo);        Button chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);        picture = (ImageView) findViewById(R.id.picture);        takePhoto.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {//                创建File对象,用于存储拍照后的照片                File outputImage = new File(getExternalCacheDir(),"output_image.jpg");                try {                    if(outputImage.exists()){                        outputImage.delete();                    }                    outputImage.createNewFile();                }catch (IOException e){                    e.printStackTrace();                }                if(Build.VERSION.SDK_INT >= 24){                    imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraalbumtest.fileprovider",outputImage);                }else{                    imageUri = Uri.fromFile(outputImage);                }//                启动相机                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");                intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);                startActivityForResult(intent,TAKE_PHOTO);            }        });        chooseFromAlbum.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                if(ContextCompat.checkSelfPermission(MainActivity.this,                        Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){                    ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);                }else{                    openAlbum();                }            }        });    }    private void openAlbum(){        Intent intent = new Intent("android.intent.action.GET_CONTENT");        intent.setType("image/*");        startActivityForResult(intent,CHOOSE_PHOTO);//打开相册    }    public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode){            case 1:                if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){                    openAlbum();                }else{                    Toast.makeText(this, "你拒绝了权限申请", Toast.LENGTH_SHORT).show();                }                break;            default:        }    }    protected void onActivityResult(int requestCode,int resultCode,Intent data) {        super.onActivityResult(requestCode, resultCode, data);        switch (requestCode) {            case TAKE_PHOTO:                if (resultCode == RESULT_OK) {                    try {//                        显示拍摄的照片                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));                        picture.setImageBitmap(bitmap);                    } catch (FileNotFoundException e) {                        e.printStackTrace();                    }                }                break;            case CHOOSE_PHOTO:                if(resultCode == RESULT_OK){//                    判断手机系统版本号                    if(Build.VERSION.SDK_INT >= 19){//                        4.4及以上系统使用这个方法处理图片                        handleImageOnKitKat(data);                    }else{//                        4.4以下用这个方法                        handleImageBeforeKitKat(data);                    }                }                break;            default:                break;        }    }    @Targetapi(19)    private void handleImageOnKitKat(Intent data) {        String imagePath = null;        Uri uri = data.getData();        Log.d("TAG", "handleImageOnKitKat: uri is " + uri);        if (DocumentsContract.isDocumentUri(this, uri)) {            // 如果是document类型的Uri,则通过document id处理            String docId = DocumentsContract.getDocumentId(uri);            if("com.android.providers.media.documents".equals(uri.getAuthority())) {                String id = docId.split(":")[1]; // 解析出数字格式的id                String selection = MediaStore.Images.Media._ID + "=" + id;                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);            } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));                imagePath = getImagePath(contentUri, null);            }        } else if ("content".equalsIgnoreCase(uri.getScheme())) {            // 如果是content类型的Uri,则使用普通方式处理            imagePath = getImagePath(uri, null);        } else if ("file".equalsIgnoreCase(uri.getScheme())) {            // 如果是file类型的Uri,直接获取图片路径即可            imagePath = uri.getPath();        }        displayImage(imagePath); // 根据图片路径显示图片    }    private void handleImageBeforeKitKat(Intent data) {        Uri uri = data.getData();        String imagePath = getImagePath(uri, null);        displayImage(imagePath);    }    @SuppressLint("Range")    private String getImagePath(Uri uri, String selection) {        String path = null;        // 通过Uri和selection来获取真实的图片路径        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);        if (cursor != null) {            if (cursor.moveToFirst()) {                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));            }            cursor.close();        }        return path;    }    private void displayImage(String imagePath) {        if (imagePath != null) {            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);            picture.setImageBitmap(bitmap);        } else {            Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show();        }    }}

        最后提醒一下,因为有些照片尺寸很大,直接加载到内存中会导致程序崩溃,需要根据需求对照片进行压缩,再加载到内存中。

 

来源地址:https://blog.csdn.net/Tir_zhang/article/details/130444401

--结束END--

本文标题: 【Android入门到项目实战-- 7.3】—— 如何调用手机摄像头和相册

本文链接: https://www.lsjlt.com/news/384220.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 【Android入门到项目实战-- 7.3】—— 如何调用手机摄像头和相册
    目录 一、调用摄像头拍照 二、打开相册选择照片         学完本篇文章可以收获如何调用手机的摄像头和打开手机相册选择图片功能。 一、调用摄像头拍照 先新建一个CameraAlbumTest项目。 修改activity_main.x...
    99+
    2023-08-31
    智能手机 android android studio 开发语言
  • vue实现调取手机摄像头和相册功能
    本文实例为大家分享了vue实现调取手机摄像头和相册的具体代码,供大家参考,具体内容如下 自己总结的手机端拍照和相册原生的方法 HTML代码 <div> //要显示的图...
    99+
    2024-04-02
  • Android如何实现调用手机摄像头录像限制录像时长
    小编给大家分享一下Android如何实现调用手机摄像头录像限制录像时长,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!具体内容如下因为服务器空间有限,所以视频时长必须有所限制。在xml中先布局一个按钮,点击开始录频。布局一个...
    99+
    2023-06-29
  • Html5中如何调用手机摄像头并实现人脸识别
    这篇文章主要介绍了Html5中如何调用手机摄像头并实现人脸识别,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。需求混合App开发,原生壳子+webApp,在web部分调用原生摄...
    99+
    2023-06-09
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作