资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

Android中使用摄像头和相册的示例

这篇文章主要介绍Android中使用摄像头和相册的示例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

目前创新互联公司已为上千的企业提供了网站建设、域名、网络空间、网站改版维护、企业网站设计、江城网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

很多 APP 应用都有用户头像功能,用户既可以调用摄像头马上拍一张美美的自拍,也可以打开相册选取一张心仪的照片作为头像。

1 调用摄像头

布局文件:




  
  

  
  

活动类代码:

public class MainActivity extends AppCompatActivity {

  private static final String TAG = "MainActivity";

  public static final int OPEN_PHOTO_REQUEST_CODE = 1;
  private Uri imgUrl = null;
  private ImageView imageView;


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    //为按钮添加【打开摄像头】事件
    findViewById(R.id.open_photo).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        File file = new File(getExternalCacheDir(), "imageView.jpg");//存储照片
        if (file.exists()) {
          file.delete();
        }
        try {
          file.createNewFile();
        } catch (IOException e) {
          e.printStackTrace();
        }


        if (Build.VERSION.SDK_INT >= 24) {//版本高于 7.0
          imgUrl = FileProvider.getUriForFile(MainActivity.this, "net.deniro.camera.fileProvider", file);
        } else {
          imgUrl = Uri.fromFile(file);
        }

        //打开摄像头
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUrl);//指定图片输出地址
        startActivityForResult(intent, OPEN_PHOTO_REQUEST_CODE);
      }
    });

    //显示拍摄的照片
    imageView = (ImageView) findViewById(R.id.img);


  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "requestCode: " + requestCode);
    Log.d(TAG, "imgUrl: " + imgUrl);
    switch (requestCode) {
      case OPEN_PHOTO_REQUEST_CODE:
        if (resultCode == RESULT_OK) {
          try {//解析图片并显示
            Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imgUrl));
            imageView.setImageBitmap(bitmap);
          } catch (FileNotFoundException e) {
            e.printStackTrace();
          }
        }
        break;
      default:
        break;
    }
  }
}

getExternalCacheDir() 可以获取 SD 卡中专门用于存放当前应用缓存数据的位置。Android6.0+ 开始,读取存放在 SD 卡中的任何其它目录都被列为危险权限,因此需要设定运行时权限才可以操作,这里使用了与应用关联的目录,所以就可以跳过这一步。

getUriForFile() 方法接收三个参数:Context对象、任意唯一的字符串与 File对象。从 android 7.0+ 系统开始,直接使用本地真实的路径被认为是不安全的,会抛出一个 FileExposedException 异常,而 FileProvider 是一种特殊的内容提供器,它使用与内容提供器类似的机制对数据进行保护。

在 AndroidManifest.xml 中注册刚才定义的内容提供器:


  
  

android:authorities 就是我们在 FileProvider.getUriForFile() 方法中传入的第二个参数。

使用 指定了 Uri 的共享路径,在此引用了 xml 资源。

在 IDEA 中可以通过快捷键 ctrl + enter 直接在 xml 文件夹下创建文件:

Android中使用摄像头和相册的示例

快捷创建

Android中使用摄像头和相册的示例

默认为 xml 文件夹

file_paths.xml:



  
  
  
  

Android 4.4 之前,还需要设置访问 SD 卡应用的关联目录权限:

 

拍照后效果:

Android中使用摄像头和相册的示例

2 从相册中选取照片

直接从相册中选取一张现有的照片比打开摄像头拍一张照片更加常用,因此,一个好的 app,应该将这两种方式都实现。

修改布局文件,加入【打开相册】按钮:


在活动类中加入打开相册选取照片的处理逻辑:

/**
 * 打开相册请求码
 */
public static final int CHOOSE_PHOTO_REQUEST_CODE = 2;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  ...
  //打开相册
  findViewById(R.id.choose_photo).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
            CHOOSE_PHOTO_REQUEST_CODE);
      } else {
        openAlbum();
      }
    }
});
/**
 * 打开相册
 */
private void openAlbum() {
  Intent intent = new Intent("android.intent.action.GET_CONTENT");
  intent.setType("image/*");
  startActivityForResult(intent, CHOOSE_PHOTO_REQUEST_CODE);
}

/**
 * 请求 WRITE_EXTERNAL_STORAGE 权限
 *
 * 相册中的照片一般是存放在 SD 卡上的,所以从 SD 卡中读取照片需要申请权限
 *
 * WRITE_EXTERNAL_STORAGE 表示读写 SD 卡的能力权限
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  switch (requestCode) {
    case CHOOSE_PHOTO_REQUEST_CODE:
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        openAlbum();
      } else {
        Toast.makeText(this, "被拒绝啦", Toast.LENGTH_SHORT).show();
      }
      break;
    default:
      break;
  }
  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  Log.d(TAG, "requestCode: " + requestCode);
  Log.d(TAG, "imgUrl: " + imgUrl);
  switch (requestCode) {
    case OPEN_PHOTO_REQUEST_CODE:
      if (resultCode == RESULT_OK) {
        try {//解析图片并显示
          Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imgUrl));
          imageView.setImageBitmap(bitmap);
        } catch (FileNotFoundException e) {
          e.printStackTrace();
        }
      }
      break;
    case CHOOSE_PHOTO_REQUEST_CODE:
      if (Build.VERSION.SDK_INT >= 19) {//4.4 及以上系统
        handleFor4_4(data);
      } else {
        handleForBefore4_4(data);
      }
      break;
    default:
      break;
  }
}

/**
 * 处理相片
 * android 4.4-
 *
 * @param data
 */
private void handleForBefore4_4(Intent data) {
  display(getImagePath(data.getData(),null));
}

/**
 * 处理相片
 * android 4.4+
 *
 * @param data
 */
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void handleFor4_4(Intent data) {
  String imagePath = null;
  Uri uri = data.getData();//需要解析
  if (DocumentsContract.isDocumentUri(this, uri)) {//是 Document 类型,使用 document id 来处理
    String documentId = DocumentsContract.getDocumentId(uri);
    String mediaDocumentAuthority = "com.android.providers.media.documents";
    String downloadDocumentAuthority = "com.android.providers.downloads.documents";
    if (mediaDocumentAuthority.equals(uri.getAuthority())) {//media 格式
      String id = documentId.split(":")[1];//数字格式的 ID
      String selection = MediaStore.Images.Media._ID + "=" + id;
      imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
    } else if (downloadDocumentAuthority.equals(uri.getAuthority())) {
      Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
      imagePath = getImagePath(contentUri, null);
    }
  } else if ("content".equalsIgnoreCase(uri.getScheme())) {//content 类型 uri
    imagePath = getImagePath(uri, null);
  } else if ("file".equalsIgnoreCase(uri.getScheme())) {//file 类型,则直接获取路径
    imagePath = uri.getPath();
  }
  display(imagePath);
}

/**
 * 显示
 * @param path
 */
private void display(String path) {
  if(path==null){
    Toast.makeText(this, "无法获取图片", Toast.LENGTH_SHORT).show();
  }else{
    imageView.setImageBitmap(BitmapFactory.decodeFile(path));
  }


}

/**
 * 获取图片路径
 *
 * @param uri
 * @param selection
 * @return
 */
private String getImagePath(Uri uri, String selection) {
  String path = null;
  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;
}

这里请求了 WRITE_EXTERNAL_STORAGE 权限,以为相册中的照片一般是存放在 SD 卡上的,所以从 SD 卡中读取照片需要申请权限。WRITE_EXTERNAL_STORAGE 表示读写 SD 卡的能力权限。

为了兼容新老版本的手机(以 Android 4.4 为分水岭),因为 Android 4.4+ 的版本返回的 Uri 需要解析才可以使用。

点击【打开相册】按钮,会弹出读取 SD 卡的权限申请:

Android中使用摄像头和相册的示例

选取照片后的效果:

Android中使用摄像头和相册的示例

以上是“Android中使用摄像头和相册的示例”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注创新互联行业资讯频道!


文章名称:Android中使用摄像头和相册的示例
URL标题:http://cdkjz.cn/article/jodhhc.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220