系統相機折騰了我兩天。。。。
本來我是照着視頻學的,然鵝出了好幾個問題,一會是指定的圖片路徑不行,一會又是調用相機後點擊確認沒反應,真的是頭疼
經過仔細查閱資料,我發現,因爲Android在API24以後對訪問權限回收,也就是說,用一個app調用另一個app,第二個app是沒有第一個app調用的文件夾的讀寫權限的。。。自從API23之後真是越來越安全了呢。。。。。
所以,需要向系統相機發送 content://URI,並授予 URI 臨時訪問權限。而進行此授權的最簡單方式是使用 FileProvider類。
步驟如下:
1.在AndroidManifest.xml中加入FileProvider註冊
<provider
android:authorities="包名.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
2.配置filepaths文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- external-path:sd ;path:你的應用保存文件的根目錄;name隨便定義-->
<!-- root-path 手機存儲根目錄 -->
<root-path path="" name="posture" />
</paths>
3.調用相機代碼
public class MainActivity extends AppCompatActivity {
private static int REQ_1=1;
private static int REQ_2=2;
private ImageView mImageView;
private String mFilePath;
private String mFileName;
Button camera2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
camera2 = findViewById(R.id.camerabutton2);
saveInRoot();//這個函數是檢測路徑用的
mImageView = findViewById(R.id.iv);
mFilePath = Environment.getExternalStorageDirectory().getPath();
mFilePath = mFilePath+"/postureTemp/";
// Uri photoUri = Uri.parse(mFilePath);
//
// String path = getSDPath();
camera2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
jump2Camera();
}
});
}
// 這是另一個按鈕調用相機的,只能在view裏顯示縮略圖
public void startCamera(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQ_1);
}
public void jump2Camera() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File path = new File(mFilePath);
if (!path.exists()) {
path.mkdirs();
}
mFileName = System.currentTimeMillis() + ".jpg";
File file = new File(path, mFileName);
if (file.exists()) {
file.delete();
}
// FileUtils.startActionCapture(this,file,REQ_2);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriForFile(this, file));
startActivityForResult(intent, REQ_2);
} else {
Log.e("main","sdcard not exists");
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == REQ_1){
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
mImageView.setImageBitmap(bitmap);
}
else if(requestCode == REQ_2){
FileInputStream fis = null;
Toast.makeText(MainActivity.this, "拍完了...", Toast.LENGTH_SHORT).show();
// 將圖片展示在imageView裏
try{
fis = new FileInputStream(mFilePath+mFileName);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
mImageView.setImageBitmap(bitmap);
}catch (FileNotFoundException e){
e.printStackTrace();
}finally {
try{
fis.close();
}
catch (IOException e){
e.printStackTrace();
}
}
}
}
}
public static Uri getUriForFile(Context context, File file) {
if (context == null || file == null) {
throw new NullPointerException();
}
Uri uri;
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.getApplicationContext(), "com.example.posturer.fileprovider", file);
Log.e("qq", "外部存儲可用..." + uri.toString());
} else {
uri = Uri.fromFile(file);
}
return uri;
}
public String getSDPath() {
File sdDir = null;
//判斷sd卡是否存在
boolean sdCardExist = Environment.getExternalStorageState()
.equals(android.os.Environment.MEDIA_MOUNTED);
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();//獲取根目錄
Log.e("qq", "外部存儲可用..." + sdDir.toString());
// Toast.makeText(MainActivity.this, "外部存儲可用...", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "外部存儲不可用...", Toast.LENGTH_SHORT).show();
}
return sdDir.toString();
}
//使用
private void saveInRoot() {
if (getSDPath()!=null) {
String fileName = getSDPath() + "/";
File file = new File(fileName,"postureTemp");//參數
if (!file.mkdir()) {
// Toast.makeText(MainActivity.this, "目錄已存在...", Toast.LENGTH_SHORT).show();
} else {
// Toast.makeText(MainActivity.this, "創建新目錄...", Toast.LENGTH_SHORT).show();
}
}
}
}
4.別忘了申請權限
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
PS
還有一個採坑點,就是按鈕的點擊事件不要放佈局文件裏,最好使用setOnClickListener監聽器,更好使~