Android 11 で android:allowBackup の挙動が少し変わります。
behavior-changes-11#device-to-device-file-transfer
If your app targets Android 11, you can no longer disable device-to-device migration of your app's files using the allowBackup attribute. The system automatically allows this functionality.
However, you can still disable cloud-based backup and restore of your app's files by setting the allowBackup attribute to false, even if your app targets Android 11.
Android 11 をターゲットにしている(targetSdkVersion = 30+)アプリでは、android:allowBackup="false" にしても device-to-device migration を無効にすることはできません。ただし、android:allowBackup="false" にしていれば cloud-based backup and restore は無効にできます。
device-to-device migration とは何かというと、Google Pixel などの local device-to-device transfer をサポートしているデバイスに別のデバイスからケーブル経由でバックアップデータを転送することです。
Backup 関係のリソース
2020年6月24日水曜日
2020年6月22日月曜日
Android アプリの詳細設定画面を開く
Settings.ACTION_APPLICATION_DETAILS_SETTINGS を使います。
adb から試すなら
startActivity(
Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
// または
// Uri.parse("package:${BuildConfig.APPLICATION_ID}")
)
)
adb から試すなら
$ adb shell
$ am start -a android.settings.APPLICATION_DETAILS_SETTINGS -d package:[packageName]
2020年6月20日土曜日
Kotlin メモ : orEmpty()
?: "" をしてくれる String?.orEmpty() という拡張関数が用意されています。
val text: String? = ...
val nonNullText: String = text.orEmpty()
2020年6月18日木曜日
Google Play の subscriptions policy の変更に対応するための参考リソース
2020/4/16 に Google Play の subscriptions policy が変更され、提供する subscription について透明性の高い情報を提供することが求められるようになりました。
subscriptions policy の変更についてのブログ
Android Developers Blog | Building user trust through more transparent subscriptions
例えば、価格や課金の頻度をちゃんと表示しましょうね、無料期間のあとは課金されることをちゃんと表示しましょうね、ということなのですが、とはいえ何がOKで何がNGなのか、何をすればいいのかこのブログではよくわからないので、関係するリソースを集めました。
チェックリスト
Subscriptions checklist
このチェックリストの最後のほうにある Learn more でいける
Academy for App Success | Set up subscriptions
の方がわかりやすいチェックリストがあります。ただし日本語だとチェックリストが出ないので、Profile で Preferred language を English にする必要があります。
↓ OK/NG の例があります(少しだけ)。
Developer Policy Center | Monetization and Ads | Subscriptions
OK/NG の例はこの動画が一番わかりやすいと思います。
おすすめは ↑ の動画を見た後に Academy for App Success | Set up subscriptions の英語版をやる、です。
subscriptions policy の変更についてのブログ
Android Developers Blog | Building user trust through more transparent subscriptions
例えば、価格や課金の頻度をちゃんと表示しましょうね、無料期間のあとは課金されることをちゃんと表示しましょうね、ということなのですが、とはいえ何がOKで何がNGなのか、何をすればいいのかこのブログではよくわからないので、関係するリソースを集めました。
チェックリスト
Subscriptions checklist
このチェックリストの最後のほうにある Learn more でいける
Academy for App Success | Set up subscriptions
の方がわかりやすいチェックリストがあります。ただし日本語だとチェックリストが出ないので、Profile で Preferred language を English にする必要があります。
↓ OK/NG の例があります(少しだけ)。
Developer Policy Center | Monetization and Ads | Subscriptions
OK/NG の例はこの動画が一番わかりやすいと思います。
おすすめは ↑ の動画を見た後に Academy for App Success | Set up subscriptions の英語版をやる、です。
2020年6月16日火曜日
WorkManager の CoroutineWorker, Worker をテストする
こういう CoroutineWorker があるとします。
TestListenableWorkerBuilder は version 2.1.0 から追加されています。
TestListenableWorkerBuilder の build() で Worker のインスタンスを取得し、doWork() を呼んで結果をチェックします。
CoroutineWorker ではなく Worker をテストするときは TestListenableWorkerBuilder ではなく TestWorkerBuilder を使います。
参考 : https://developer.android.com/topic/libraries/architecture/workmanager/how-to/testing-worker-impl
class SendHelloWorker(
private val context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val name = inputData.getString("name") ?: return Result.failure()
val api = (context.applicationContext as MyApplication)
.appComponent
.api()
return try {
api.sendHello("Hello $name")
Result.success()
} catch (e: Exception) {
Result.failure()
}
}
}
まず CoroutineWorker や Worker をテストするには worker-testing artifact を使います。
testImplementation "androidx.work:work-testing:$work_version"
CoroutineWorker のテストには TestListenableWorkerBuilder を使います。
TestListenableWorkerBuilder は version 2.1.0 から追加されています。
TestListenableWorkerBuilder の build() で Worker のインスタンスを取得し、doWork() を呼んで結果をチェックします。
class SendHelloWorkerTest {
private lateinit var api: MyApi
private lateinit var context: Context
@Before
fun setup() {
api = mock()
val appComponent: AppComponent = mock()
whenever(appComponent.api()).thenReturn(api)
val application = MyApplication()
application.setAppComponent(appComponent)
context = mock()
whenever(context.applicationContext).thenReturn(application)
}
@Test
fun doWork() {
val worker = TestListenableWorkerBuilder<SendHelloWorker>(
context,
inputData = Data.Builder()
.putString("name", "Android")
.build()
)
.build()
runBlocking {
val result = worker.doWork()
assertThat(result).isEqualTo(ListenableWorker.Result.success())
verify(api).sendHello("Hello Android")
}
}
@Test
fun doWork_fail() {
val worker = TestListenableWorkerBuilder<SendHelloWorker>(
context,
inputData = Data.Builder()
.putString("name", "Android")
.build()
)
.build()
whenever(api.sendHello("Hello Android")).thenThrow(RuntimeException())
runBlocking {
val result = worker.doWork()
assertThat(result).isEqualTo(ListenableWorker.Result.failure())
verify(api).sendHello("Hello Android")
}
}
}
CoroutineWorker ではなく Worker をテストするときは TestListenableWorkerBuilder ではなく TestWorkerBuilder を使います。
参考 : https://developer.android.com/topic/libraries/architecture/workmanager/how-to/testing-worker-impl
2020年6月10日水曜日
Kotlin : Uri から ByteArray を取得する (Uri to ByteArray)
Kotlin の readBytes() 拡張関数を使うとすっきり。
val context: Context = ...
val uri: Uri = ...
val byteArray: ByteArray? = context.contentResolver
.openInputStream(uri)
?.use { it.readBytes() }
2020年6月2日火曜日
androidx.test.ext:truth を使ったときに IllegalAccessError が出たらバージョンを 1.3.0 以降にする
androidx.test.ext.truth にある IntentSubject などを使うとき
というエラーが出ます。
IntentSubject 内で Subject の actual() メソッドにアクセスしているのですが、これが 0.42 のときは protected だったのが package private に変わってアクセスできなくなったのが原因です。
そのため、この新しい Truth に対応した androidx.test.ext:truth のバージョンを使えば OK です。
com.google.truth:truth:0.42
androidx.test.ext:truth:1.2.0
だと動くのですが、Truth のバージョンを以下のように 1.0.1 にすると
com.google.truth:truth:1.0.1
androidx.test.ext:truth:1.2.0
java.lang.IllegalAccessError: tried to access method com.google.common.truth.Subject.actual()Ljava/lang/Object; from class androidx.test.ext.truth.content.IntentSubject
というエラーが出ます。
IntentSubject 内で Subject の actual() メソッドにアクセスしているのですが、これが 0.42 のときは protected だったのが package private に変わってアクセスできなくなったのが原因です。
そのため、この新しい Truth に対応した androidx.test.ext:truth のバージョンを使えば OK です。
com.google.truth:truth:1.0.1
androidx.test.ext:truth:1.3.0-rc01