Android 11で令和に標準で対応予定

Androidのバージョンはグングン上がります。
今やそろそろAndroid 11がリリースされつつあります。
そのAndroid 11にて、ついに日本の元号「令和」が標準APIで対応するようです。

# 結論

結論を真っ先に述べます。

- Android 11(R)にて、ついに日本の元号「令和」が標準APIで対応するようです。
- すでにAPIレベル24からAndroid標準APIはICUを取り込んでいます。
- でもAPIレベル24～29の間は「令和」には対応していません。「平成」どまりです。

# [閑話]コードネームとかAPIレベルとか

ところで、お菓子の名前のコードネームですが、「Q」からやんなくなりました。

KitKatとかLollipopとかMarshmallowとかNougatとかOreoとかPieとか。時折、登録商標も混ざりながらも。
Androidっ子たちは、「Q」から綴りが始まるお菓子が何になるのかワクワクしてたのに、Googleが「お菓子の名前はもうやめた」と言い出して。

Android 10は「Q」。そろそろリリースされる11は「R」です。

Androidの「R」で「令和」に対応...まっまさか！その「R」は、「Reiwa」のRか？！なんちゃって。

そして、この10とか11というバージョン番号、そしてコードネームとは別に、開発者にとって重要な番号は「[APIレベル](https://developer.android.com/guide/topics/manifest/uses-sdk-element?hl=ja)」です。
Android 8.0はOreoであり、APIレベルは26です。が、Android 8.1となると、同じくOreoなんですが、APIレベルは27です。ややこしい！

そして「R」に割り当てられるAPIレベルの番号は...？それは当記事の最後の方に記しましたので、お楽しみに。（じらしてスミマセン）

# IBM社製のICUというライブラリ

[http://site.icu-project.org/home](http://site.icu-project.org/home)

「International Components for Unicode」の略だそうです。とにかく色々と便利なAPIが収録されています。
オープンソースソフトウェアです。

##  ICUのJapaneseCalendarクラス

`com.ibm.icu.util.JapaneseCalendar`クラスは、日本の元号に対応しています。
最初の元号「大化」から現代まで。南北朝時代をどう扱っているか、というマニアックなところまで私は検証していませんが。

```java:本能寺の変
import java.util.Locale;

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.JapaneseCalendar;

public class Honnoujinohen {
    public static void main(String[] args) {
        JapaneseCalendar jpCalendar = new JapaneseCalendar();
        DateFormatSymbols dfs = new DateFormatSymbols(jpCalendar, Locale.JAPANESE);
        DateFormat dateFormat = new SimpleDateFormat("Gyy年MM月dd日", dfs);
        dateFormat.setCalendar(jpCalendar);

        // 「本能寺の変」1582年6月2日
        int year = 1582;
        int month = 6;
        int day = 2;
        String s = dateFormat.format(new GregorianCalendar(year, month - 1, day).getTime());
        System.out.println(s);
    }
}
```

![landmark_honnouji_fire.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100612/c3be0d6f-cf76-3cbb-4fa2-199709367e73.png)


```console:実行結果
天正10年06月02日
```

大河ドラマファンや歴女には堪りませんね。麒麟がくる。「天が正しい」と書く元号だったのか。
ああ、応仁の乱。天保の改革。安政の大獄。元号に思いを馳せるだけで脳内で時代を駆け巡れます。

このICUが「令和」に対応したのは、2019年4月17日リリースのバージョン64.2からです。

# Android標準API

Android標準APIでは、APIレベル24（Android 7.0 Nougat）からICUを取り込みました。
取り込んだだけあって、パッケージも変わっております。例えば、前出の`JapaneseCalendar`クラスは、[`android.icu.util.JapaneseCalendar`](https://developer.android.com/reference/android/icu/util/JapaneseCalendar)です。

そして。ついに。Android 11（R）のAPIレベルで、

```java:
public static final int REIWA
```

が追加されます！まさかのint enumパターーーン！！！いやーーーん！！！
しょうがねぇだろ、IBM社製のICUがそもそもint enumパターーーンなんだからーーーん！！！

# サンプルアプリ

こんなアプリを作ってみました。

![Screenshot_1585201324.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100612/09eb8ede-b64b-f232-eb68-734190c32c45.png)


「建武の新政」は、鎌倉幕府を倒した後醍醐天皇が、1333年7月17日からスタートさせた新政策ですが、当日はまだ元号が「元弘」だというヒッカケ問題ですね。今度の2学期中間試験に出そうだな。

![nigaoe_godaigo_tennou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100612/94079923-819a-b04b-15bb-1cce47c9ebe4.png)

![Screenshot_1585200766.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100612/048029b7-81ae-093a-03d5-9530b29480f5.png)

平成から令和へ。

![Screenshot_1585200774.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100612/d62722e4-e1f3-1f09-afce-d1aae8443ccd.png)

開発環境は以下の通りです。

> Android Studio 3.6.1
> Build #AI-192.7142.36.36.6241897, built on February 27, 2020
> Runtime version: 1.8.0_212-release-1586-b04 amd64
> VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
> Windows 10 10.0
> GC: ParNew, ConcurrentMarkSweep
> Memory: 1237M
> Cores: 8
> Registry: ide.new.welcome.screen.force=true
> Non-Bundled Plugins:

## Gradleの設定

Android 11（R）のAPIレベルで作らなければなりません。
Gradle設定ファイルに以下のようにします（一部略）。

```groovy:build.gradle
android {
    compileSdkVersion 'android-R'
    buildToolsVersion "29.0.2"

    defaultConfig {
        applicationId "com.example.gengou"
        minSdkVersion 24
    }

    compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }
}
```

この記事執筆時点では、Android 11（R）のAPIレベルに番号が割り当てられていません。まだプレビュー版だからのようです。正式版がリリースされたら、おそらく`30`になると推測されます。

`minSdkVersion`は最低でも`24`にしなければなりません。なぜなら前述にありますように、ICUがAndroid標準APIに組み込まれたのが、APIレベル24からだからです。

## Activity

```java:MainActivity.java
package com.example.gengou;

import android.icu.text.DateFormat;
import android.icu.text.DateFormatSymbols;
import android.icu.text.SimpleDateFormat;
import android.icu.util.GregorianCalendar;
import android.icu.util.JapaneseCalendar;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText year = findViewById(R.id.year);
        EditText month = findViewById(R.id.month);
        EditText day = findViewById(R.id.day);
        TextView gengo = findViewById(R.id.gengou);

        findViewById(R.id.button).setOnClickListener(v -> {
            int y = Integer.parseInt(year.getText().toString());
            int m = Integer.parseInt(month.getText().toString());
            int d = Integer.parseInt(day.getText().toString());
            JapaneseCalendar jpCalendar = new JapaneseCalendar();
            DateFormatSymbols dfs = new DateFormatSymbols(jpCalendar, Locale.JAPANESE);
            DateFormat dateFormat = new SimpleDateFormat("Gyy年MM月dd日", dfs);
            dateFormat.setCalendar(jpCalendar);
            String s = dateFormat.format(new GregorianCalendar(y, m - 1, d).getTime());
            gengo.setText(s);
        });
    }
}
```

# Android標準APIではなく、IBMのICUで令和に対応する

せっかくAndroid標準APIで令和に対応するってのに！それを使わずに、IBMのICUで令和に対応するって、なんか本末転倒！
と思われるかもしれませんが、以下の理由でそんなコトもしてみたいのです。

- Android標準APIで令和に対応するのは、「R」からだ。それはいい。
- ICUがAndroid標準APIに組み込まれたのは、APIレベル24（Android 7.0「N」）だ。
- であれば、Gradleの設定で`minSdkVersion`は最低でも24でないと、令和うんぬん以前に、`android.icu`パッケージが使えない。
- だけど、自分の作るアプリは、Androidのバージョン6とか5とか4とかにも対応したい！

ということで、そのやり方です。

## Gradleの設定

```groovy:build.gradle
dependencies {
    implementation 'com.ibm.icu:icu4j:64.2'
}
```

依存ライブラリとして追記してSyncNowですね。令和対応の`64.2`以上を指定します。

## プログラム

名前衝突を避けるためにも`import`文はこうなります。

```java:パッケージにご注意
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.JapaneseCalendar;

import java.util.Locale;
```

`Locale`だけは、安定の`java.util`パッケージですね。
これでAndroid 6とか5とか4とかでも、令和対応できます。

# [おまけ]当たり前ですが。

「光文」という元号は、ICUにはありませんので、ご安心を。

![Screenshot_1585202068.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100612/710f739e-8738-8fcd-cfc6-14e1736b2cdd.png)

以上です。