Android 7.1 の新機能を試す

Android 7.1 の新機能の整理、及び、簡単な動作確認を行いました。
※動作確認はシミュレータで行っています。
※正確なアップデート情報については、下記開発者向けサイトを参考にして下さい。
https://developer.android.com/about/versions/nougat/android-7.1.html

## App Shortcuts

#### 概要

ランチャーに新しいアプリショートカット機能が追加

- ランチャーアイコン長押しでショートカット表示
- アプリショートカットをタップすると、関連するアクションにジャンプ
- アプリショートカットは、静的・動的に作成することが可能
- アプリショートカットは、最大４つまで？（各アプリ）
- 本機能がサポートされているランチャーで利用可能

#### 実行

簡単なサンプルを作成して実行してみました。
まず準備として、AndroidManifest.xml にアプリショートカット用の meta-data タグを追加します。

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.co.sample.appshortcuttest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- アプリショートカット -->
            <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />

        </activity>
    </application>

</manifest>
```

次に、xml フォルダを作成し、以下の shortcuts.xml ファイルを配置します。

##### 静的作成する場合
静的に表示したいアプリショートカットはこのファイルに shortcut タグとして追加します。
ここでは、"Run" と "Bicycle" を追加しました。

```xml
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">

  <!-- Run -->
  <shortcut
      android:shortcutId="run"
      android:enabled="true"
      android:icon="@mipmap/ic_run"
      android:shortcutShortLabel="@string/sc_run_short_label"
      android:shortcutLongLabel="@string/sc_run_long_label"
      android:shortcutDisabledMessage="@string/sc_run_disabled_massage">
    <intent
        android:action="android.intent.action.VIEW"
        android:targetPackage="jp.co.sample.appshortcuttest"
        android:targetClass="jp.co.sample.appshortcuttest.MainActivity" />
    <categories android:name="android.shortcut.conversation" />
  </shortcut>

  <!-- Bicycle -->
  <shortcut
      android:shortcutId="bicycle"
      android:enabled="true"
      android:icon="@mipmap/ic_bicycle"
      android:shortcutShortLabel="@string/sc_bicycle_short_label"
      android:shortcutLongLabel="@string/sc_bicycle_long_label"
      android:shortcutDisabledMessage="@string/sc_bicycle_disabled_massage">
    <intent
        android:action="android.intent.action.VIEW"
        android:targetPackage="jp.co.sample.appshortcuttest"
        android:targetClass="jp.co.sample.appshortcuttest.MainActivity" />
    <categories android:name="android.shortcut.conversation" />
  </shortcut>

  <!-- 追加したいアプリショートカットがあれば、追記する -->

</shortcuts>
```

　アプリインストール後、ランチャー画面でアイコンを長押しすると、
　追加した２つのアプリショートカットが表示されます。
　また、一覧からドロップするとアプリショートカットアイコンが作成出来ます。
　<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/5b7cb6c2-f91d-6fba-7c33-f07c9b03e593.png" width="300px"> <img src="https://qiita-image-store.s3.amazonaws.com/0/134550/24f3329d-339a-55e3-0f8d-2cad4cd04496.png" width="300px">

##### 動的作成する場合

動的に作成する場合は、以下のようなコードで操作します。
アプリショートカットの追加・更新・削除・無効・有効の一通りの動作を試してみます。

・アプリショートカットを追加
　addDynamicShortcuts() メソッドで追加します。

```java
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
ShortcutInfo shortcut = new ShortcutInfo.Builder(getApplicationContext(), "car")
        .setShortLabel("Car")
        .setLongLabel("Car!")
        .setIcon(Icon.createWithResource(getApplicationContext(), R.mipmap.ic_car))
        .setIntent(new Intent(Intent.ACTION_VIEW,
                Uri.parse("https://www.mysite.example.com/")))
        .build();
shortcutManager.addDynamicShortcuts(Arrays.asList(shortcut));
```

　一覧にアプリショートカットが追加されました。
　また、一覧からドロップするとアプリショートカットアイコンが作成出来ます。
　<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/cd8794e0-9125-3440-00a7-d495accbfd26.png" width="300px"> <img src="https://qiita-image-store.s3.amazonaws.com/0/134550/c9ecba16-f6ea-8982-1d4e-2e0b5b0201a6.png" width="300px">

・アプリショートカット更新
 updateShortcuts() メソッドで更新します。

```java
ShortcutInfo shortcut = new ShortcutInfo.Builder(getApplicationContext(), "car")
        .setShortLabel("Update Car")
        .setLongLabel("Update Car!")
        .setIcon(Icon.createWithResource(getApplicationContext(), R.mipmap.ic_car_update))
        .setIntent(new Intent(Intent.ACTION_VIEW,
                Uri.parse("https://www.mysite.example.com/")))
        .build();
shortcutManager.updateShortcuts(Arrays.asList(shortcut));
```

　アプリショートカットが更新されました、ドロップしたアイコンも更新されています。
　<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/aa8208af-96f5-018f-e467-f44e264ff348.png" width="300px">

・アプリショートカット削除
　removeDynamicShortcuts() メソッドで削除します。

```java
shortcutManager.removeDynamicShortcuts(Arrays.asList("car"));
```
　一覧からアプリショートカットが削除されました、ドロップしたアイコンは残ってしまいます。
　現状、コードから削除することは出来ないようです。
　<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/20d68258-6e07-b33f-9e67-1d76161be961.png" width="300px">

・アプリショートカット無効
　disableShortcuts() メソッドで無効にします。

```java
shortcutManager.disableShortcuts(Arrays.asList("car"));
```
　一覧から対象のアプリショートカットが消え、ドロップしたアイコンはグレーアウトされます。
　タップしても反応しなくなります。
　<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/66a718bf-6c55-f5d5-9eac-d3b529e5f658.png" width="300px">

・アプリショートカット有効
　enableShortcuts() メソッドで有効にします。

```java
shortcutManager.enableShortcuts(Arrays.asList("car"));
```
　ドロップしたアイコンのグレーアウトが解除されました。
　しかし、一覧にアプリショートカットは再表示されないようです。
　<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/386065be-fbaf-13a7-9546-69d9312b92ff.png" width="300px">

>メモ：
アプリショートカットは、静的作成のみ・動的作成のみ・混合した場合の３ケースを試したが
最大４つまでしか作成出来なかった。


***

## Image Keyboard Support

#### 概要

- 画像などのコンテンツをソフトキーボードから直接アプリ内のテキストエディタへ送信可能になった
- アプリ側・ソフトキーボード側の双方での対応が必要
- v13 Support Library（revision 25.0.0.以降）での提供のため古いバージョンでも利用可能

#### 実行

Google Developers で公開されている[サンプル](https://developer.android.com/about/versions/nougat/android-7.1-samples.html)を実行してみました。
サンプルでは、EditText からのソフトキーボード連携時に FileProvider 経由で画像ファイルを受け取り、
アプリの背景に配置された WebView にコンテンツを表示させています。

まず、事前に設定画面などからキーボードの種類をサンプルのソフトキーボードに設定しておきます。
その後、アプリを起動し EditText を選択するとソフトキーボードが出現します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/6ccbfef0-056f-0211-23bc-a9d6acadcb2d.png" width="300px">


ソフトキーボードからそれぞれの連携用のボタンをタップすると、
アプリ側で画像コンテンツが取得でき、gif、png、webp の画像が背景に表示されました。

|[INSERT GIF]|[INSERT PNG]|[INSERT WEBP]|
|:-----------------|:------------------|:------------------|
|<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/3bf477ad-59de-491f-df49-b2913c036b25.png" width="300px">|<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/a6d4bc4c-b9e7-a774-dfc8-e7dedbaeb21c.png" width="300px">|<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/3c0f44f8-94d3-2f76-51ea-93e03be0cf4b.png" width="300px">|


#### サンプル

今回使用したサンプルは以下となります。

|項目|サンプルコード|
|:-----------------|:------------------|
|アプリ|[Image keyboard app sample](https://developer.android.com/samples/CommitContentSampleApp/index.html) [[Download]](https://developer.android.com/downloads/samples/CommitContentSampleApp.zip)|
|ソフトキーボード|[Image keyboard IME sample](https://developer.android.com/samples/CommitContentSampleIME/index.html) [[Download]](https://developer.android.com/downloads/samples/CommitContentSampleIME.zip)|

>ソフトキーボード側のサンプルコードは、そのまま使用するとアプリ連携時にクラッシュが発生するため
環境設定以外にも ImageKeyboard.java の下記部分を修正をする必要がありました。

>```java
(修正前)
private static final String AUTHORITY = "com.example.android.supportv13.sampleime.inputcontent";
```

>```java
(修正後)
private static final String AUTHORITY = "com.example.android.commitcontent.ime.inputcontent";        
```

***

## New Professional Emoji

#### 概要

- 新しい絵文字が追加
- Paint.hasGlyph() で新しい絵文字を動的に確認可能

***

## Enhanced Live Wallpaper Metadata

#### 概要

- ライブ壁紙に関するラベル、説明、作成者などの既存のメタデータ属性や新しい属性（コンテキストURL・タイトル）を提供

***

## Round Icon Resources

#### 概要

- Round Icon を定義出来るようになった
- アプリアイコンが要求されるとき、フレームワークはデバイスのビルド設定に応じて
android:icon または android:roundIcon を返すため、android:icon と android:roundIcon の
両方のリソースを定義する必要がある
- [Asset Studio](https://developer.android.com/studio/write/image-asset-studio.html#access) を使って Round Icon をデザイン出来る

#### 実行

Round Icon 用のリソースを用意し、AndroidManifest.xml の android:roundIcon に定義します。

```xml
<application
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/[Round Icon 用のリソース]]"
    ~
```
>AndroidStudio 2.2.2 (Gradle 2.14.1/Android Plugin version 2.2.2) の環境だと
AndroidManifest.xml で android:roundIcon が エラーとして表示されますが実行可能でした。
2.2.3 環境へアップデートすることでエラーが表示されなくなります。

この状態でアプリをインストールすると、
Round Icon がサポートされている端末では、android:roundIcon に定義されたアイコンが表示され、
定義されていない場合は、android:icon に定義されたアイコンが表示されます。

Round デザインに特化したアイコンを使いたい場合などは、専用のリソースを用意し、
AndroidManifest.xml に定義する必要があるようです。

また、非対応デバイスを含めた動作確認は以下となります。

||対応デバイス|非対応デバイス|
|:------------------|:------------------|:------------------|
|roundIcon 定義あり|Round Icon 表示|通常アイコン表示|
|roundIcon 定義なし|通常アイコン表示|通常アイコン表示|
>四角い画像を Round Icon として定義しても そのまま四角いアイコンが表示されました。

***

## Storage Manager Intent

#### 概要

- StorageManager クラスに新しいアクション ACTION_MANAGE_STORAGE が追加された
- インテント起動することでユーザーをシステムの領域解放画面に移動可能

#### 実行

以下のように Intent起動を行うとシステムの領域解放画面へ移動する。

```java
Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
startActivity(intent);
```

起動された画面
<img src="https://qiita-image-store.s3.amazonaws.com/0/134550/69eb1add-9199-b238-cca2-0261c3fc8392.png" width="300px">

***

## Improved VR Thread Scheduling

#### 概要

- VRスレッドを指定出来るようになった
- VRスレッドとして指定するには ActivityManager.setVrThread() をコールする
- アプリが VRモード中は、システムが積極的にスケジューリングして待ち時間を最小限に抑える
- プロセスは１度に１つの VRスレッドしか持つことが出来ない
- 実行可能時間に制限を課す可能性がある

***

## Demo User Hint

#### 概要

- デモユーザーとしてデバイスが実行されているかどうかを確認できるようになった
- UserManager.isDemoUser() で確認可能

>メモ：
開発者向けオプションのデモモード設定を有効にしても True にならなかった。
無関係のようです。

***

## APIs for Carriers and Calling Apps

#### 概要
キャリアと電話アプリ向けに新しい電話機能を提供

- マルチエンドポイントコーリング
- CDMA音声プライバシー
- Visual Voicemail のソースタイプのサポート
- ビデオ電話を管理するキャリア設定オプション

>詳細不明

***

## New Screen Densities for Wear Devices

#### 概要

Wearデバイス用の画面密度定義が追加された
- DENSITY_260
- DENSITY_300
- DENSITY_340

***

以上、簡単に新機能を試してみました。

<br>