Kotlin 无法从arFragment-ARCore-Augmented Face拍摄照片

Kotlin 无法从arFragment-ARCore-Augmented Face拍摄照片,kotlin,arcore,Kotlin,Arcore,我遵循这里的代码,但未能捕获我的ArFragment。请帮帮我。 该项目的链接: 始终获取IOException:“未能将位图保存到磁盘” 我的写作片段: class FaceArFragment : ArFragment() { override fun getSessionConfiguration(session: Session?): Config { return Config(session).apply { augmentedFaceMode =

我遵循这里的代码,但未能捕获我的ArFragment。请帮帮我。

该项目的链接:

始终获取IOException:“未能将位图保存到磁盘”

我的写作片段:

    class FaceArFragment : ArFragment() {

    override fun getSessionConfiguration(session: Session?): Config {
        return Config(session).apply { augmentedFaceMode = Config.AugmentedFaceMode.MESH3D }
    }

    override fun getSessionFeatures(): MutableSet<Session.Feature> {
        return EnumSet.of(Session.Feature.FRONT_CAMERA)
    }
    override fun getAdditionalPermissions(): Array<String?>? {
        val additionalPermissions = super.getAdditionalPermissions()
        val permissionLength =
            additionalPermissions?.size ?: 0
        val permissions =
            arrayOfNulls<String>(permissionLength + 1)
        permissions[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE
        if (permissionLength > 0) {
            System.arraycopy(
                additionalPermissions,
                0,
                permissions,
                1,
                additionalPermissions!!.size
            )
        }
        return permissions
    }

    /**
     * Override to turn off planeDiscoveryController. Plane trackables are not supported with the
     * front camera.
     */
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        val layout = super.onCreateView(inflater, container, savedInstanceState) as FrameLayout
        planeDiscoveryController.apply {
            hide()
            setInstructionView(null)
        }
        return layout
    }
}
class FaceArFragment:ArFragment(){
覆盖getSessionConfiguration(会话:会话?):配置{
返回配置(会话).apply{augmentedFaceMode=Config.augmentedFaceMode.MESH3D}
}
重写getSessionFeatures():MutableSet{
返回枚举集(会话功能前摄像头)
}
覆盖getAdditionalPermissions():数组{
val additionalPermissions=super.getAdditionalPermissions()
val许可长度=
其他权限?.size?:0
val权限=
阵列长度(许可长度+1)
权限[0]=Manifest.permission.WRITE\u外部存储
如果(许可长度>0){
System.arraycopy(
附加权限,
0,
权限,
1.
附加权限!!.size
)
}
返回权限
}
/**
*覆盖以关闭planeDiscoveryController。的不支持平面可跟踪项
*前摄像头。
*/
覆盖创建视图(
充气机,
容器:视图组?,
savedInstanceState:捆绑?
):查看{
val layout=super.onCreateView(充气机、容器、savedInstanceState)作为框架布局
planeDiscoveryController.apply{
隐藏()
setInstructionView(空)
}
返回布局
}
}
我的活动XML:

<layout 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">

    <data>

        <variable
            name="takePictureViewModel"
            type="com.example.breakablecam.screens.takingPicture.TakePictureViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/face_fragment_cointanier"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:paddingBottom="16dp"
            app:layout_constraintBottom_toTopOf="@+id/takePhotoView"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:visibility="visible">

            <fragment
                android:id="@+id/face_fragment"
                android:name="com.example.breakablecam.screens.takingPicture.FaceArFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </androidx.fragment.app.FragmentContainerView>

        <ImageView
            android:id="@+id/backArrow"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="16dp"
            android:visibility="gone"

            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />

        <ImageView
            android:id="@+id/stickerView"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginBottom="16dp"
            android:onClick="@{() -> takePictureViewModel.tapSticker()}"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/takePhotoView"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent" />

        <ImageView
            android:id="@+id/stickerView1"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginStart="16dp"
            android:layout_marginBottom="16dp"
            android:visibility="gone"
            android:onClick="@{() -> takePictureViewModel.tapSticker1()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

        <ImageView
            android:id="@+id/takePhotoView"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginBottom="16dp"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/makeupView"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/stickerView" />

        <ImageView
            android:id="@+id/makeupView"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginBottom="16dp"
            android:onClick="@{() -> takePictureViewModel.tapMakeupView()}"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/takePhotoView" />

        <ImageView
            android:id="@+id/makeupView1a"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginStart="16dp"
            android:layout_marginBottom="16dp"
            android:onClick="@{() -> takePictureViewModel.tapMakeup1aView()}"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            tools:visibility="visible" />

        <ImageView
            android:id="@+id/makeupView1"
            android:layout_width="@android:dimen/app_icon_size"
            android:layout_height="@android:dimen/app_icon_size"
            android:layout_marginStart="16dp"
            android:visibility="gone"
            app:layout_constraintBottom_toTopOf="@id/makeupView1a"
            app:layout_constraintStart_toStartOf="parent"
            tools:visibility="visible" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

我的活动:

    class TakePictureActivity : AppCompatActivity() {

    private lateinit var viewModel: TakePictureViewModel
    private lateinit var arFragment: FaceArFragment
    private var modelRenderable: ModelRenderable? = null
    private var meshTexture: Texture? = null
    private val faceNodeMap = HashMap<AugmentedFace, AugmentedFaceNode?>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityTakePictureBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_take_picture)

        viewModel = ViewModelProvider(this).get(TakePictureViewModel::class.java)


        binding.apply {
            viewModel.apply {
                setStickerViewSource(stickerView)
                setMakeupViewSource(makeupView)
                setTakePhotoViewSource(takePhotoView)
                setMakeup1ViewSource(makeupView1)
                setMakeup1aViewSource(makeupView1a)
                setSticker1ViewSource(stickerView1)
                setBackArrowSource(backArrow)
            }
        }

        binding.takePictureViewModel = viewModel
        binding.lifecycleOwner = this

        viewModel.makeupTap.observe(this, Observer { check ->
            if (check == 1) {
                binding.apply {
                    makeupView.visibility = GONE
                    takePhotoView.visibility = GONE
                    stickerView.visibility = GONE
                    makeupView1.visibility = VISIBLE
                    makeupView1a.visibility = VISIBLE
                    backArrow.visibility = VISIBLE
                    val params =
                        faceFragmentCointanier.layoutParams as ConstraintLayout.LayoutParams
                    params.bottomToTop = R.id.makeupView1
                }
                viewModel.doneTapMakeup()
            }
        })

        viewModel.stickerTap.observe(this, Observer { check ->
            if (check == 1) {
                binding.apply {
                    makeupView.visibility = GONE
                    takePhotoView.visibility = GONE
                    stickerView.visibility = GONE
                    stickerView1.visibility = VISIBLE
                    backArrow.visibility = VISIBLE
                    val params =
                        faceFragmentCointanier.layoutParams as ConstraintLayout.LayoutParams
                    params.bottomToTop = R.id.stickerView1
                }
                viewModel.doneTapSticker()
            }
        })
        binding.apply {
            backArrow.setOnClickListener {
                makeupView.visibility = VISIBLE
                takePhotoView.visibility = VISIBLE
                stickerView.visibility = VISIBLE
                makeupView1.visibility = GONE
                makeupView1a.visibility = GONE
                backArrow.visibility = GONE
                stickerView1.visibility = GONE
                backArrow.visibility = GONE
                val params =
                    faceFragmentCointanier.layoutParams as ConstraintLayout.LayoutParams
                params.bottomToTop = R.id.takePhotoView
            }
        }

        arFragment = supportFragmentManager.findFragmentById(R.id.face_fragment) as FaceArFragment
        val sceneView = arFragment.arSceneView
        sceneView.cameraStreamRenderPriority = Renderable.RENDER_PRIORITY_FIRST
        val scene = sceneView.scene
        loadTexture(R.drawable.makeup1a)
        loadModel(R.raw.fox_face)
        viewModel.makeupTap1a.observe(this, Observer { check ->
            when (check) {
                1 -> {
                    scene.addOnUpdateListener {
                        val collection: Collection<AugmentedFace>? =
                            sceneView.session?.getAllTrackables(AugmentedFace::class.java)
                        collection?.forEach { face ->
                            if (!faceNodeMap.containsKey(face)) {
                                val faceNode = AugmentedFaceNode(face)
                                faceNode.apply {
                                    setParent(scene)
                                    faceMeshTexture = meshTexture
                                }
                                faceNodeMap[face] = faceNode
                            }
                        }

                        val iterator = faceNodeMap.entries.iterator()
                        while (iterator.hasNext()) {
                            val entry = iterator.next()
                            val face = entry.key
                            if (face.trackingState == TrackingState.STOPPED) {
                                val faceNode = entry.value
                                faceNode!!.setParent(null)
                                iterator.remove()
                            }
                        }
                    }
                }
                2 -> {
                    val children: List<Node> =
                        ArrayList(arFragment.arSceneView.scene.children)
                    for (node in children) {
                        if (node is AnchorNode) {
                            if (node.anchor != null) {
                                node.anchor?.detach()
                            }
                        }
                        if (node !is Camera && node !is Sun) {
                            node.setParent(null)
                        }
                    }
                }
            }
        })
        viewModel.sticker1Tap.observe(this, Observer { check ->
            when (check) {
                1 -> {
                    scene.addOnUpdateListener {
                        val collection: Collection<AugmentedFace>? =
                            sceneView.session?.getAllTrackables(AugmentedFace::class.java)
                        collection?.forEach { face ->
                            if (!faceNodeMap.containsKey(face)) {
                                val faceNode = AugmentedFaceNode(face)
                                faceNode.apply {
                                    setParent(scene)
                                    faceRegionsRenderable = modelRenderable
                                }
                                faceNodeMap[face] = faceNode
                            }
                        }

                        val iterator = faceNodeMap.entries.iterator()
                        while (iterator.hasNext()) {
                            val entry = iterator.next()
                            val face = entry.key
                            if (face.trackingState == TrackingState.STOPPED) {
                                val faceNode = entry.value
                                faceNode!!.setParent(null)
                                iterator.remove()
                            }
                        }
                    }
                }
                2 -> {
                    val children: List<Node> =
                        ArrayList(arFragment.arSceneView.scene.children)
                    for (node in children) {
                        if (node is AnchorNode) {
                            if (node.anchor != null) {
                                node.anchor?.detach()
                            }
                        }
                        if (node !is Camera && node !is Sun) {
                            node.setParent(null)
                        }
                    }
                }
            }
        })
        binding.takePhotoView.setOnClickListener {
            takePhoto()
        }
    }

    private fun loadTexture(tex: Int) {
        Texture.builder()
            .setSource(this, tex)
            .build()
            .thenAccept { texture -> meshTexture = texture }
    }
    private fun loadModel(mod: Int) {
        ModelRenderable.builder()
            .setSource(this, mod)
            .build()
            .thenAccept { model ->
                model.apply {
                    isShadowCaster = false // optional
                    isShadowReceiver = false
                }
                modelRenderable = model
            }
    }
    private fun generateFilename(): String? {
        val date =
            SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault())
                .format(Date())
        return Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES
        ).toString() + File.separator + "Sceneform/" + date + "_screenshot.jpg"
    }

    @Throws(IOException::class)
    private fun saveBitmapToDisk(bitmap: Bitmap, filename: String) {
        val out = File(filename)
        if (!out.parentFile.exists()) {
            out.parentFile.mkdirs()
        }
        try {
            FileOutputStream(filename).use { outputStream ->
                ByteArrayOutputStream().use { outputData ->
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputData)
                    outputData.writeTo(outputStream)
                    outputStream.flush()
                    outputStream.close()
                }
            }
        } catch (ex: IOException) {
            throw IOException("Failed to save bitmap to disk", ex)
        }
    }

    private fun takePhoto() {
        val filename = generateFilename()
        val view: ArSceneView = arFragment.getArSceneView()

        // Create a bitmap the size of the scene view.
        val bitmap = Bitmap.createBitmap(
            view.width, view.height,
            Bitmap.Config.ARGB_8888
        )

        // Create a handler thread to offload the processing of the image.
        val handlerThread = HandlerThread("PixelCopier")
        handlerThread.start()
        // Make the request to copy.
        PixelCopy.request(view, bitmap, { copyResult ->
            if (copyResult === PixelCopy.SUCCESS) {
                try {
                    saveBitmapToDisk(bitmap, filename!!)
                } catch (e: IOException) {
                    val toast = Toast.makeText(
                        this, e.toString(),
                        Toast.LENGTH_LONG
                    )
                    toast.show()
                    return@request
                }
                val snackbar = Snackbar.make(
                    findViewById(android.R.id.content),
                    "Photo saved", Snackbar.LENGTH_LONG
                )
                snackbar.setAction(
                    "Open in Photos"
                ) { v: View? ->
                    val photoFile = File(filename)
                    val photoURI = FileProvider.getUriForFile(
                        this,
                        this.getPackageName()
                            .toString() + ".ar.codelab.name.provider",
                        photoFile
                    )
                    val intent = Intent(Intent.ACTION_VIEW, photoURI)
                    intent.setDataAndType(photoURI, "image/*")
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                    startActivity(intent)
                }
                snackbar.show()
            } else {
                val toast = Toast.makeText(
                    this,
                    "Failed to copyPixels: $copyResult", Toast.LENGTH_LONG
                )
                toast.show()
            }
            handlerThread.quitSafely()
        }, Handler(handlerThread.looper))
    }
}
class TakePictureActivity:AppCompativity(){
私有lateinit变量viewModel:TakePictureViewModel
私有lateinit var arFragment:FaceArFragment
私有变量modelRenderable:modelRenderable?=null
私有纹理:纹理?=null
private val faceNodeMap=HashMap()
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
val绑定:ActivityTakePictureBinding=
DataBindingUtil.setContentView(此,R.layout.activity\u拍摄照片)
viewModel=ViewModelProvider(this.get)(TakePictureViewModel::class.java)
应用{
viewModel.apply{
setStickerViewSource(粘贴视图)
setMakeupViewSource(makeupView)
setTakePhotoViewSource(takePhotoView)
setMakeup1ViewSource(makeupView1)
设置MakeUp1aViewSource(makeupView1a)
设置ticker1viewsource(粘贴视图1)
SetBackArrow源(反箭头)
}
}
binding.takePictureViewModel=viewModel
binding.lifecycleOwner=此
viewModel.makeupTap.observe(这个,observator{check->
如果(检查==1){
应用{
makeupView.visibility=消失
takePhotoView.visibility=消失
stickview.visibility=消失
makeupView1.visibility=可见
makeupView1a.visibility=可见
backArrow.visibility=可见
val params=
faceFragmentCointanier.layoutParams作为ConstraintLayout.layoutParams
params.bottomToTop=R.id.makeupView1
}
viewModel.doneTapMakeup()
}
})
viewModel.stickerTap.observe(此,观察者{检查->
如果(检查==1){
应用{
makeupView.visibility=消失
takePhotoView.visibility=消失
stickview.visibility=消失
粘贴视图1.visibility=可见
backArrow.visibility=可见
val params=
faceFragmentCointanier.layoutParams作为ConstraintLayout.layoutParams
params.bottomToTop=R.id.view1
}
viewModel.doneTapSticker()
}
})
应用{
backArrow.setOnClickListener{
makeupView.visibility=可见
takePhotoView.visibility=可见
粘贴视图。可见性=可见
makeupView1.visibility=消失
makeupView1a.visibility=消失
backArrow.visibility=消失
粘贴视图1.visibility=消失
backArrow.visibility=消失
val params=
faceFragmentCointanier.layoutParams作为ConstraintLayout.layoutParams
params.bottomToTop=R.id.takePhotoView
}
}
arFragment=supportFragmentManager.findFragmentById(R.id.face\u fragment)作为FaceArFragment
val sceneView=arFragment.arSceneView
sceneView.cameraStreamRenderPriority=Renderable.RENDER\u PRIORITY\u FIRST
val scene=sceneView.scene
loadTexture(R.可拉深。化妆1A)
载荷模型(R.raw.fox_面)
viewModel.makeupTap1a.observe(这个,observator{check->
何时(检查){
1 -> {
scene.addOnUpdateListener{
val收集:收集=
sceneView.session?.getAllTrackables(AugmentedFace::class.java)
集合?.forEach{face->
如果(!faceNodeMap.containsKey(面)){
val faceNode=增强的faceNode(面)
faceNode.apply{
setParent(场景)
<application android:requestLegacyExternalStorage="true" ... > ... </application>