首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么“拍照”按钮不起作用?

为什么“拍照”按钮不起作用?
EN

Stack Overflow用户
提问于 2021-04-25 12:15:11
回答 1查看 118关注 0票数 0

我试着做了一些应用程序,所以我从GitHub那里借来了一个。当我点击“拍照”按钮时,它会说应用程序没有响应。我认为这个问题与申请相机许可有关。我将targetSdkVersion从22升级到28,现在它不起作用了。有人能帮我吗。

这里是selectimageactivity.java:

代码语言:javascript
运行
复制
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.microsoft.projectoxford.face.samples.R;

import java.io.File;
import java.io.IOException;

// The activity for the user to select a image and to detect faces in the image.
public class SelectImageActivity extends AppCompatActivity {
    // Flag to indicate the request of the next task to be performed
    private static final int REQUEST_TAKE_PHOTO = 0;
    private static final int REQUEST_SELECT_IMAGE_IN_ALBUM = 1;

    // The URI of photo taken with camera
    private Uri mUriPhotoTaken;

    // When the activity is created, set all the member variables to initial state.
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_select_image);
    }

    // Save the activity state when it's going to stop.
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("ImageUri", mUriPhotoTaken);
    }

    // Recover the saved state when the activity is recreated.
    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mUriPhotoTaken = savedInstanceState.getParcelable("ImageUri");
    }

    // Deal with the result of selection of the photos and faces.
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode)
        {
            case REQUEST_TAKE_PHOTO:
            case REQUEST_SELECT_IMAGE_IN_ALBUM:
                if (resultCode == RESULT_OK) {
                    Uri imageUri;
                    if (data == null || data.getData() == null) {
                        imageUri = mUriPhotoTaken;
                    } else {
                        imageUri = data.getData();
                    }
                    Intent intent = new Intent();
                    intent.setData(imageUri);
                    setResult(RESULT_OK, intent);
                    finish();
                }
                break;
            default:
                break;
        }
    }

    // When the button of "Take a Photo with Camera" is pressed.
    public void takePhoto(View view) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if(intent.resolveActivity(getPackageManager()) != null) {
            // Save the photo taken to a temporary file.
            File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
            try {
                File file = File.createTempFile("IMG_", ".jpg", storageDir);
                mUriPhotoTaken = Uri.fromFile(file);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriPhotoTaken);
                startActivityForResult(intent, REQUEST_TAKE_PHOTO);
            } catch (IOException e) {
                setInfo(e.getMessage());
            }
        }
    }

    // When the button of "Select a Photo in Album" is pressed.
    public void selectImageInAlbum(View view) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(intent, REQUEST_SELECT_IMAGE_IN_ALBUM);
        }
    }

    // Set the information panel on screen.
    private void setInfo(String info) {
        TextView textView = (TextView) findViewById(R.id.info);
        textView.setText(info);
    }
}

然后是build.gradle(模块):

代码语言:javascript
运行
复制
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28

    defaultConfig {
        applicationId "com.microsoft.projectoxford.faceapisample"
        minSdkVersion 22
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')

    // Include local lib mostly for debug purpose.
    // implementation project(':lib')

    // Use the following line to include client library for Face API from Maven Central Repository
    implementation 'com.microsoft.projectoxford:face:1.4.4'
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'com.android.support.constraint:constraint-layout:2.0.4'


    implementation "com.android.support:design:28.0.0"

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

}

这就是我在logcat上遇到的错误。在这里输入图像描述

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-25 15:39:06

从您的logcat中,您将获得FileUriExposedExceptiom,您需要创建FileProvider并使用相同的FileProvider。

原因是针对Android7.0(APILevel24)和更高的应用程序,通过包边界传递file://URI会导致FileUriExposedException。

以下是更多信息,以及如何拍照和使用FileProvider

https://developer.android.com/training/camera/photobasics

https://developer.android.com/reference/androidx/core/content/FileProvider

首先,必须在标记内的FileProvider文件中声明此AndroidManifest.xml:

代码语言:javascript
运行
复制
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
        ...>
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.example.myapp.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
        ...
    </application>
</manifest>

接下来,创建一个名为xml的资源目录并创建一个fileprovider.xml。假设您希望授予对应用程序的特定外部存储目录的访问权限(这需要请求其他权限),则可以如下所示:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!-- See table below.  The external-files-path DOES NOT require external storage permissions. -->
    <external-files-path
        name="images"
        path="Pictures" />

    <!--Uncomment below to share the entire application specific directory -->
    <!--<external-path name="all_dirs" path="."/>-->
</paths>

最后,您将使用FileProvider类将File对象转换为内容提供程序:

代码语言:javascript
运行
复制
// getExternalFilesDir() + "/Pictures" should match the declaration in fileprovider.xml paths
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");

// wrap File object into a content provider. NOTE: authority here should match authority in manifest declaration
bmpUri = FileProvider.getUriForFile(MyActivity.this, "com.example.myapp.fileprovider", file);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67253299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档