shibafu528/Yukari

Android 12 対応

shibafu528 opened this issue · 2 comments

https://developer.android.com/about/versions/12?hl=ja

TODO

  • Android 11 対応を完了させる (#283)
  • リリースノートを読む
  • コンポーネントのエクスポートの安全性を改善
  • ペンディング インテントの可変性
  • トーストのデザイン変更

動作の変更点: すべてのアプリ

戻るボタンを押してもルート ランチャー アクティビティが終了しない

戻るボタンのイベントをオーバーライドしているため、動作の変更は発生していない。

ただし、Android 12以降の普及によって戻るボタンの操作がActivityの終了ではないという認識が広まった場合、変更したほうが良い可能性がある。

動作の変更点: Android 12をターゲットとするアプリ

コンポーネントのエクスポートの安全性を改善

AndroidManifestにおいてIntent filterを使うコンポーネントには android:exported 属性が必須になる。ランチャーからの起動および外部からの呼び出しを想定しているコンポーネントは true で設定する。

ペンディング インテントの可変性

通常はimmutableで大丈夫だが、mutableに設定する必要があるケースもあるとのこと。

トーストのデザイン変更

Android 12 では、トーストの外見が変更されています。トーストは、2 行のテキストに制限され、テキストの横にアプリアイコンが表示されるようになりました。

アプリが Android 12(API レベル 31)以上をターゲットにしている場合、トーストは 2 行のテキストに制限され、テキストの横にアプリアイコンが表示されます。このテキストの行の長さは画面サイズによって異なるため、テキストはできるだけ短くすることをおすすめします。
https://developer.android.com/guide/topics/ui/notifiers/toasts?hl=ja

トーストのデザイン変更で影響を受けそうな場所

行数が多い
完了画面を作れば良いか?

Toast.makeText(getApplicationContext(),
String.format("修復が終了しました\n========\n%d 破損していたブックマーク\n%d 修復成功\n%d エラー",
values[0], values[1], values[2]),
Toast.LENGTH_LONG).show();

行数が多い
精査すれば、このチェック自体不要な可能性がある。どうしても必要な場所では適宜マウントを確認すべきだし、無くても動くなら内部ストレージにフォールバックしたほうが良い。
→ そもそも現代のAndroidで外部ストレージがマウントされてないことあるのか? どうテストすればいいのか分からない……。とりあえず放置しても良さそう。

if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(getApplicationContext(), getString(R.string.error_storage_not_found), Toast.LENGTH_LONG).show();
finish();
return;
}

行数が多い
MainActivityだし、SnackBarか単に適当にView追加して結果表示すれば良さそう。
→ あまり意味なさそうだから省略する

Toast.makeText(getApplicationContext(), String.format("クエリ実行完了\n%s\n処理時間: %d ms\n抽出件数: %d 件", rawQuery, time, resultElements.size()), Toast.LENGTH_LONG).show();

たぶん2行は越える

// if error...
Toast.makeText(getApplicationContext(),
"このメディアを開くことが出来ません。\n元ツイートのパーマリンクを添えて作者に連絡してみるといいかもしれません。",
Toast.LENGTH_LONG).show();

たぶん2行は越える

Toast.makeText(getApplicationContext(),
"カメラとの連携をキャンセルする際、一時ファイルの削除に失敗しました。\nもしギャラリーにゴミが増えていたら始末をお願いします。",
Toast.LENGTH_SHORT).show();

行数が多い

Toast.makeText(activity, "アプリの登録中にエラーが発生しました\nインスタンス名が正確であること、サーバがダウンしていないことを確認してください", Toast.LENGTH_LONG).show()

微妙に溢れそう

Toast.makeText(activity, "認証成功!\nメニューの「Active Accounts」からストリーミングの設定ができます。", Toast.LENGTH_LONG).show()

行数が多い

if (args.getBoolean(ARGUMENT_ALL_R4S, false)) {
if ("toshi_a".equals(targetUser.getScreenName())) {
Toast.makeText(getActivity(), "アアアッwwwwミクッター作者に全垢r4sかまそうとしてるゥwwwwwwwwwwwww\n\n(toshi_a proof を発動しました)", Toast.LENGTH_LONG).show();
} else {

行数が多い

Toast.makeText(getActivity(), "ユーザー情報の取得に失敗しました\n\n" + e.getErrorMessage(), Toast.LENGTH_LONG).show();

たぶん溢れる
ここに関しては、機能廃止の方向にしたいが……
→ 非推奨扱いとして、設定画面に注釈を入れた。

final String text = tickerHeader + actionBy.getScreenName() + "\n" +
status.getUser().getScreenName() + ": " + status.getText();
handler.post(() -> Toast.makeText(context.getApplicationContext(),
text,
Toast.LENGTH_LONG)
.show());

レートリミット通知

行数が多い

is TwitterException -> {
when (exception.statusCode) {
429 -> Toast.makeText(context,
String.format("[@%s]\nレートリミット超過\n次回リセット: %d分%d秒後\n時間を空けて再度操作してください",
userRecord.ScreenName,
exception.rateLimitStatus.secondsUntilReset / 60,
exception.rateLimitStatus.secondsUntilReset % 60),
Toast.LENGTH_SHORT).show()
403 -> {
if (exception.errorCode == 93) {
Toast.makeText(context,
String.format("[@%s]\nアクセス権エラー: %d:%d\n" +
"DMへのアクセスが制限されています。\n" +
"一度アプリ連携を切って認証を再発行してみてください。",
userRecord.ScreenName,
exception.errorCode,
exception.errorMessage),
Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context,
String.format("[@%s]\nアクセス権エラー: %d:%d\n%s",
userRecord.ScreenName,
exception.statusCode,
exception.errorCode,
exception.errorMessage),
Toast.LENGTH_SHORT).show()
}
}
else -> {
val template: String
if (exception.isCausedByNetworkIssue) {
template = "[@%s]\n通信エラー: %d:%d\n%s"
} else {
template = "[@%s]\nエラー: %d:%d\n%s"
}
Toast.makeText(context,
String.format(template,
userRecord.ScreenName,
exception.statusCode,
exception.errorCode,
exception.errorMessage),
Toast.LENGTH_SHORT).show()
}
}
}

行数が多い

} catch (e: TwitterException) {
e.printStackTrace()
when (e.statusCode) {
429 -> {
showToast(String.format("[AutoReload:@%s]\nレートリミット超過\n次回リセット: %d分%d秒後",
user.ScreenName,
e.rateLimitStatus.secondsUntilReset / 60,
e.rateLimitStatus.secondsUntilReset % 60))
val waitSeconds = maxOf(e.rateLimitStatus.secondsUntilReset, 60)
Log.d(LOG_TAG, "Next after $waitSeconds secs. user: @${user.ScreenName}")
Thread.sleep(waitSeconds * 1000L)
}
else -> {
showToast(String.format("[AutoReload:@%s]\n通信エラー: %d:%d\n%s",
user.ScreenName,
e.statusCode,
e.errorCode,
e.errorMessage))
Log.d(LOG_TAG, "Next after 60 secs. user: @${user.ScreenName}")
Thread.sleep(60000L)
}
}
} catch (e: InterruptedException) {
throw e
} catch (e: Exception) {
e.printStackTrace()
showToast(String.format("[AutoReload:@%s]\nエラーが発生しました\n%s",
user.ScreenName,
e.javaClass.simpleName))
Log.d(LOG_TAG, "Next after 60 secs. user: @${user.ScreenName}")
Thread.sleep(60000L)
}

mruby関連

たぶん2行は越える

} catch (MRubyException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),
String.format("Procの実行中にMRuby上で例外が発生しました\n%s", e.getMessage()),
Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(getApplicationContext(),
String.format("Procの実行に失敗しました\ntwicca_action :%s の宣言で適切なブロックを渡していますか?", slug),
Toast.LENGTH_LONG).show();
}

行数が多い

onMainThread {
Toast.makeText(context, "未実装ですヽ('ω')ノ三ヽ('ω')ノ\nもうしわけねぇもうしわけねぇ\n\n呼び出し情報 =>\n" + options.inspect(), Toast.LENGTH_SHORT).show()
}

たぶん溢れる

if (pluginDir.exists() && !pluginDir.isDirectory()) {
showToast("[Yukari exvoice]\nプラグインディレクトリのあるべき場所にファイルがあります。どかしていただけますか?");
} else {

行数が多い

if (result.getFailure().length > 0) {
StringBuilder sb = new StringBuilder("プラグインの読み込みに失敗しました:");
for (String slug : result.getFailure()) {
sb.append("\n");
sb.append(slug);
}
showToast(sb.toString());
}

トーストのデザイン変更は明らかな部分について対応完了。targetSdkVersionを上げた後に発見されたものは個別に対応する。