安卓开发|java|点击按钮调用相机并在屏幕上显示||所有代码均已测试可以使用,非源文件分享,每个文件复制粘贴使用兼容性更佳

调用相机

根据我微薄的安卓开发经验,直接给你们源文件会出各种各样的兼容性问题,所有我把需要使用的文件内容分类放置,你们逐个复制粘贴即可。
这里有我之前的错误案例以及一些log,还有更改后的分析。希望对你有帮助,如果可以请给我一个评论或赞,这是我持续上传笔记的动力。

前面部分是我根据网上的各种教程写的程序,会出一些错误,我对此进行了分析和改错。不想看的朋友可以直接跳转到“修改后”。

[[#layout]]
[[#mainActivity.java]]
[[#AndroidManifest.xml]]
[[#@xml/paths]]
[[#log以及报错问题]]

layout


<?xml version="1.0" encoding="utf-8"?>  
<androidx.constraintlayout.widget.ConstraintLayout 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">

<Button  
android:id="@+id/take_photo"  
android:layout_width="wrap_content"  
android:layout_height="wrap_content"  
android:text="take it">

<ImageView  
android:id="@+id/photo"  
android:layout_width="0dp"  
android:layout_height="145dp"  
  
app:layout_constraintBottom_toBottomOf="parent"  
app:layout_constraintEnd_toEndOf="parent"  
app:layout_constraintStart_toStartOf="parent"  
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

//布局使用了constratlayout,使用了一个按钮控件和一个,imageView控件,imageView控件没有设置图片

返回标题

mainActivity.java

import 内容省略

package com.example.tackemac;  
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);  

//onCreate 函数重写,绑定mainactivity.

Button takePhoto = (Button) findViewById(R.id.take_photo);  
picture = (ImageView) findViewById(R.id.photo);

//控件ID绑定

takePhoto.setOnClickListener(new View.OnClickListener() {  
@Override  
public void onClick(View view) {  
Log.e(TAG,"onclickstart");  
File outputImage = new File(getExternalCacheDir(),  
"output_image.jpg");  

//点击事件
// IO流,将图片存储到output_image.jpg中
//CacheDir–外部缓存地址


try {  
if (outputImage.exists()) {  
outputImage.delete();  
}  
outputImage.createNewFile();  
} catch (IOException e) {  
e.printStackTrace();  
}

//捕获异常,检测是否存在相同照片
//检测SDK版本,做不同版本的适配↓

if (Build.VERSION.SDK_INT >= 24) {  
Log.e(TAG,"onclickif");  
imageUri = FileProvider.getUriForFile(MainActivity.this,  
"com.exanple.cameraablumtest.flieprovider",  
outputImage);  
} else {  
imageUri = Uri.fromFile(outputImage);  
}  
Log.e(TAG,"newintent");  

//跳转到系统相机中

Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");  
Log.e(TAG,"intent");  
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  
// MainActivity.this.startActivityForResult(intent,TAKE_PHOTO);  
startActivityForResult(intent, TAKE_PHOTO);  
}  
});  
}  

/*==重写onActivityResult结果函数
request Code --启动活动请求,用于区分是哪个请求的结果
result Code --返回结果, result_OK标示成功。
Intent data --返回跳转的对象
Bitmap–一种照片图像数据的表示形式
BitmaoFactory.decodeStream --把获取的图片解码为bitmap图

@Override  
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {  
super.onActivityResult(requestCode, resultCode, data);  
Log.e(TAG,"onActiviyResult");  
  
switch (requestCode) {  
  
case TAKE_PHOTO:  
if (resultCode == RESULT_OK) {  
try {  
Bitmap bitmap = BitmapFactory.decodeStream(  
getContentResolver().openInputStream(imageUri));  
} catch (FileNotFoundException e) {  
e.printStackTrace();  
}  
}  
break;  
default:  
break;  }  
}  }

返回标题

AndroidManifest.xml

获取的照相和存储权限

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
package="com.example.tackemac"  
xmlns:tools="http://schemas.android.com/tools">  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<!--声明访问SD卡权限↑-->

<application  
android:allowBackup="true"  
android:dataExtractionRules="@xml/data_extraction_rules"  
android:fullBackupContent="@xml/backup_rules"  
android:icon="@mipmap/ic_launcher"  
android:label="@string/app_name"  
android:roundIcon="@mipmap/ic_launcher_round"  
android:supportsRtl="true"  
android:theme="@style/Theme.Tackemac"  
tools:targetApi="31">  




<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>  
<provider  
android:authorities="com.example.bicameralism.file-provider"  
android:name="androidx.core.content.FileProvider"  
android:grantUriPermissions="true">  
<meta-data  
android:name="android.support.FILE_PROVIDER_PATHS"  
<!-- 请注意这里-->
android:resource="@xml/file_paths"/>  


</provider>  
</application>  
</manifest>

指定Uri共享路径,@xml/paths

返回标题

@xml/paths

在res中新建一个xml文件夹,再在其中新建一个名为file_path.xml的文件

<?xml version="1.0" encoding="utf-8"?>  
<paths  
xmlns:android="http://schemas.android.com/apk/res/android">  
<external-path  
name="my_images"  
path="output_image.jpg"/>  
</paths>

<‘external-path’>指定Uri共享,path表示具体路径,空值表示整个SD卡共享,这里仅共享ouput_image.jpg的路径

返回标题

log以及报错问题

  E  avc:  denied  { find } for service=netd pid=7894 uid=2000 scontext=u:r:shell:s0 tcontext=u:object_r:netd_service:s0 tclass=service_manager
2024-10-14 19:40:05.070  1369-1369  SELinux                 servicemanager                       E  avc:  denied  { find } for service=android.service.gatekeeper.IGateKeeperService pid=7894 uid=2000 scontext=u:r:shell:s0 tcontext=u:object_r:gatekeeper_service:s0 tclass=service_manager
2024-10-14 19:40:05.076  1369-1369  SELinux                 servicemanager                       E  avc:  denied  { find } for service=installd pid=7894 uid=2000 scontext=u:r:shell:s0 tcontext=u:object_r:installd_service:s0 tclass=service_manager
2024-10-14 19:40:07.315  1700-1910  JavaBinder    

system_server                    


E  !!! FAILED BINDER TRANSACTION !!!  (parcel size = 108)
//怀疑是传输问题,但是没有找到解决方法

==E !!! FAILED BINDER TRANSACTION !!! (parcel size = 108)
//怀疑是传输问题,但是没有找到解决方法
//android似乎对图片传输大小有限制,看网上的各种方法没有完全理解

2024-10-14 19:40:08.106  7938-7962  <no-tag>                com.example.tackemac                 D  HostConnection::get() New Host Connection established 0xa2c76140, tid 7962
2024-10-14 19:40:10.572  1369-1369  SELinux                 servicemanager                       E  avc:  denied  { find } for service=netd pid=7966 uid=2000 scontext=u:r:shell:s0 tcontext=u:object_r:netd_service:s0 tclass=service_manager
2024-10-14 19:40:10.574  1369-1369  SELinux                 servicemanager                       E  avc:  denied  { find } for service=android.service.gatekeeper.IGateKeeperService pid=7966 uid=2000 scontext=u:r:shell:s0 tcontext=u:object_r:gatekeeper_service:s0 tclass=service_manager
2024-10-14 19:40:10.575  1369-1369  SELinux                 servicemanager                       E  avc:  denied  { find } for service=installd pid=7966 uid=2000 sconte

返回标题

修改后

返回标题

maiActivity.java

定义常量

/*
Oncreate函数绑定布局
定义常量
request_image_caputue =1 – 请求图像捕捉;
REQUEST_CAMERA_PERMISSION = 100 --请求相机许可

*/

public class MainActivity extends AppCompatActivity {  
  
  
static final int REQUEST_IMAGE_CAPTURE = 1;  
static final int REQUEST_CAMERA_PERMISSION = 100;
Oncreate函数绑定布局
@Override  
protected void onCreate(Bundle savedInstanceState) {  
super.onCreate(savedInstanceState);  
setContentView(R.layout.activity_main);
}
定义常量

/*
定义常量
request_image_caputue =1 – 请求图像捕捉;
REQUEST_CAMERA_PERMISSION = 100 --请求相机许可

*/


public void takePictureIntent(View view) {  
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) {  
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);  
} else {  
dispatchTakePictureIntent();  
}  
}

点击事件

/*
点击事件!
判断是否拥有相机权限,如果没有就请求相机权限,如果有就使用Intent打开相机。
GRANTED --授予
if中
ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED
为授予权限的判定

*/

请求使用相机
public void  dispatchTakePictureIntent(){
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    try {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    } catch (ActivityNotFoundException e) {
        // display error state to the user
        Log.e("WarningMsg","相机打开失败!");
    }
}

/*
使用Intent打开相机↑dispatchTakePictureIntent()
这个名为dispatchTakePictureIntent的方法主要用于启动设备的相机应用以拍摄照片。
----
传入一个请求码REQUEST_IMAGE_CAPTURE。当相机应用拍摄完照片后,结果会返回到调用这个方法的活动(Activity)中,通过重写onActivityResult方法可以处理拍摄后的照片数据。
------
如果在尝试启动相机的过程中抛出了ActivityNotFoundException异常,说明设备上没有能够响应这个拍照意图的应用程序。此时会捕获这个异常,并在日志中打印错误信息“相机打开失败!”,

*/

请求认证

/*
----
==请求认证回调函数,public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)请求权限成功之后,再次回调打开相机


- `requestCode`:用于区分不同的权限请求。这里通过与常量`REQUEST_CAMERA_PERMISSION`比较,确定是否是相机权限请求的结果。

permissions`:一个字符串数组,包含被请求的权限名称。

- `grantResults`:一个整数数组,对应`permissions`数组中的权限请求结果,`PackageManager.PERMISSION_GRANTED`表示权限被授予,`PackageManager.PERMISSION_DENIED`表示权限被拒绝。==↓

*/

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  
super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
if (requestCode == REQUEST_CAMERA_PERMISSION) {  
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
dispatchTakePictureIntent();//打开相机  
} else {  
Toast.makeText(this, "无法获取拍照权限", Toast.LENGTH_SHORT).show();  }  
}  }
把内容传入imageView

/*
==在拍照完成后,激活该方法,把照片数写入ImageView
protected void onActivityResult(int requestCode, int resultCode, Intent data)
- requestCode:用于区分不同的启动子活动的请求码。在这个例子中,通过与特定的常量REQUEST_IMAGE_CAPTURE进行比较,确定返回的结果是否来自相机拍照的请求。

resultCode:表示子活动的返回结果状态码。这里通过与RESULT_OK进行比较,确定拍照操作是否成功。
----
-Intent data:子活动返回的包含数据的意图(Intent)对象。
----
- 使用findViewById(R.id.iv)找到一个ImageView控件,然后通过imageView.setImageBitmap(imageBitmap)将拍摄的照片设置为这个ImageView的显示内容。↓↓
==
*/

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Bundle extras = data.getExtras();
        Bitmap imageBitmap = (Bitmap) extras.get("data");
        ImageView imageView = findViewById(R.id.iv);
        imageView.setImageBitmap(imageBitmap);
    }
}


[返回标题](#调用相机)
### AndroidMainfest.xml

==权限添加==

```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

返回标题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值