LoginSignup
3
1

More than 3 years have passed since last update.

2020年10月版ActivityResultAPIを使ってみた。

Posted at

kotlinやandroidxの勉強も兼ねて、以前作った自作androidアプリケーションを一から作り直しているんですが、Activity#startActivityForResultは代わりにActivityResultAPIを使う事を薦められているとの事。

いきなり使うのはためらうので、まずはテストプロジェクトで試してみましたが、まぁ、何ていうかその…。

トラブル解決に自信があるなら別にいいけど、そうでないならあと1年は様子見でいいよ。

テストしてみる。

とりあえずテストした結果を書いておきます。

まず、「build.gradle」に依存関係を書きます。

dependencies {
    implementation "androidx.activity:activity:1.2.0-alpha08"
    implementation "androidx.activity:activity-ktx:1.2.0-alpha08"
    implementation "androidx.fragment:fragment:1.3.0-alpha06"
}

ここに注目。
というのも、結構新しいAPIなので、仕様が変わっていて、ネットの情報が間違っている事も多い。
ぶっちゃけ、これから書く内容も、将来的には間違いかもしれないですよ。

そして、Activityのコード。

MainActivity.kt
package com.example.test1012a

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.content.Intent
import android.app.Activity
import android.util.Log
import androidx.activity.result.contract.ActivityResultContracts
import android.widget.Toast

//private const val REQUEST_CODE = 1

class MainActivity(): AppCompatActivity(), View.OnClickListener {

    private val launcher = registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
        Log.d("test1012a", String.format("uri = %s.", uri.toString()))
        this@MainActivity.getContentResolver().openOutputStream(uri)?.writer()?.use {
            it.write("Hello, world!\n")
        }
    }

    protected override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        this.setContentView(R.layout.main)

        this.findViewById<View>(R.id.button1).setOnClickListener(this)
    }

    override fun onClick(view: View)
    {
        when (view.getId()) {
            R.id.button1 -> {
//              val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
//                  this.addCategory(Intent.CATEGORY_OPENABLE)
//                  this.type = "*/*"
//              }
//              this.startActivityForResult(intent, REQUEST_CODE)
                this.launcher.launch("hoge")
            }
        }
    }

//  override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?)
//  {
//      if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
//          resultData?.data?.also {
//              this.findViewById<TextView>(R.id.result).setText(it.toString())
//          }
//      }
//  }
}

以下、ハマった点です。

prepareCallではなく、registerForActivityResult

先の公式サイトのとおりに記述したら、「prepareCall」でビルドエラー。
「なんでじゃー」と叫びつついろいろと探してみると、バージョン1.2.0-alpha04の変更点に以下の記述が。

prepareCall() メソッドの名前が、ここの ComponentActivity と Fragment 1.3.0-alpha04 の両方で、registerForActivityResult() に変更されました。

ドキュメント直しておけよーー。
(これに限らず、最近のandroidのドキュメントはおざなりになっていない?量が膨大になってきたのはわかりますけど、わかりますけどね)

「Can only use lower 16 bits for requestCode」

めでたくビルドが通って、実行してみると、ボタンを押した時点でアプリが落ちてしまいます。
ログを見てみると、「Can only use lower 16 bits for requestCode」とのエラーが出力。

実は、当初依存関係に「fragment:1.3.0-alpha06」は含んでいなかったのです。いやだって、fragment使ってないし。
でも、試しに加えてみたら、エラーが発生しなくなりました。もしかすると、FragmentActivity辺りが古いせいなのかもしれません。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1