Learn to Live and Live to Learn

IT(たまにビジネス)に関する記事を読んで、考えて、使ってみたことをまとめる場。

Android M パーミッション対応

Android 6 Marshmallowからパーミッションの取得タイミングが変わった

これまでGoogle Playでのインストール時に全てのパーミッションを要求されていました。
皆さんの中にも「このパーミッションは何に使われてるの?」と疑問に思われたことのある方や、「使わない機能で必要なパーミッションを求められている」と感じたことのある方がいらっしゃるのではないでしょうか。
Android 6(APIレベル23)以降ではそんな気がかりはなくなります。
Google Playでは何もせず、それぞれのパーミッションが必要なタイミングで要求できる(される)ようになります。

実装

実装方法はこんな感じです。(ちょっとややこしくなった感)

AndroidManifest.xml

<!-- RECORD_AUDIO=マイクのパーミッションを例とする -->
<uses -permission android:name="android.permission.RECORD_AUDIO" />

MainActivity.java

...
private static final int REQUEST_CODE = 1;
...
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 権限がない時
    if (PermissionChecker.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {

        // 許可ダイアログの再表示判定
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO) {
            new AlertDialog.Builder(this)
                .setTitle("パーミッションの追加説明")
                .setMessage("このアプリで○○するにはマイクのパーミッションが必要です。")
                .setPositiveButton("設定" new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // パーミッションを要求する
                        ActivityCompat.requestPermissions(MainActivity.this,
                            new String[]{Manifest.permission.RECORD_AUDIO},
                            REQUEST_CODE);
                    }
                })
                .create()
                .show();
            return;
        }

        // 一度もパーミッションの要求をしていない or 今後表示しないにチェックをした上で”許可しない”にした時
        // 今後表示しないにしている場合はrequestPermissionsしても何も起こらないので、実質初回パーミッション要求時の対応
        // 初回とは初回起動という意味ではなく、パーミッションのON/OFF切り替え時も含まれる
        ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.RECORD_AUDIO},
            REQUEST_CODE);
        }
    }
}

@Override
// パーミッション要求の結果を受け取る
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // パーミッションが必要な処理
            } else {
                // パーミッションが得られなかった場合の対応
            }
        }
    }
}
...

参考になるサイト

システム パーミッションの使用 | Android Developers
CheckSelfPermissionの注意事項 - リスクファインダーブログ
初心者のためのM Permissions入門 | TechBooster

データベースの中身を見る(Android)

データベースの中身を誰でも見られる場所に移動する

run-asをつけるとアプリユーザ(アプリ自身)としてコマンドを実行できます。
しかし、データベースの中身を見たいのは一般ユーザなので、run-asした状態で一般ユーザの見られるSDCardにデータベースをコピーします。
終わったらexitしてください。

$ ./adb shell
$ run-as {package_name} cat databases/<database_name>.db > /sdcard/<database_name>.db  
$ exit

データベース名が分からない場合はこちらで確認できます。

$ ./adb shell
$ run-as {package_name}
$ cd databases
$ ls

データベースをPCにプルする

$ ./adb pull /sdcard/<database_name>.db .

sqlite3で中身を確認する

sqlite3 <database_name>.dbしたあとは普通のSQLと同じ感じでいけました。

$ sqlite3 <database_name>.db 
sqlite> select * from <table_name>;

sqlite3が存在するかはwhich sqlite3とかで確認してください。
Macは標準であるっぽいです。

APK署名スキームv2を使い、インストール速度を向上させる(Android N対応)

Android Nから導入された署名スキームv2ではAPKの検証速度が大幅に向上している

Android 7.0 では、APK 署名スキーム v2 というアプリのインストール時間を高速化したり、APK ファイルに無許可の変更が行われないようにしたりする新しいアプリ署名スキームが導入されています。
公式より

署名はAndroid Studio or apksignerでできる

二通りの方法があります。
1). apksigner

$ cd {...}/Android/sdk/build-tools/{version}
$ ./apksigner sign --ks {YourApp}.keystore --v1-signing-enabled true --v2-signing-enabled true {YourApp}.apk

2). Android Studio 2.2 と Gradle 2.2 用の Android プラグイン(未確認)

確認はapksignerコマンドでできる

v1, v2ともに署名されていることが確認できます。
下位互換のため、今まで通りv1での署名も必要です。

$ ./apksigner verify -v {YourApp}.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Number of signers: 1

参考

developer.android.com developers-jp.googleblog.com

アプリのOpenSSLバージョンを確認する

OpenSSLのバージョン確認は必要

脆弱性があるとお客様を危険に晒すことになるので大事なことです。
もちろんGoogle PlayのリリースではセキュリティスキャンとしてOpenSSLのバージョン確認も行われています。
アプリの OpenSSL の脆弱性への対処方法 - Google ヘルプによると、OpenSSL1.02f/1.01rより前のバージョンはだめとのことです。
fとかrの部分はアルファベット順で1.01qはNG、1.01sはOKという認識です。

OpenSSLとは、暗号通信プロトコルの機能を実装したオープンソースのライブラリ

セキュリティーを要求される通信のためのプロトコルである「SSLプロトコル」と「TLSプロトコル」を容易に実装できるオープンソースパッケージ。ソフトウェアライブラリ。

OpenSSLとは - はてなキーワードより

確認は、解凍したapkからOpenSSLでgrepする

$ cd {$project}/{$module}/build/outputs/apk
$ unzip -p {$name}.apk | strings | grep "OpenSSL"

unzipは解凍です。-pオプションでパイプ(stdout)に抽出してくれ、元ファイルがどうこうなることはありません。
stringsはプリント可能な文字列を検索してくれます。
grepgrep "hoge"hogeを検索します。

ちなみにGoogle Playのベータ版テストでリリース前にセキュリティスキャンができる

なので、Google Playは上手く使いこなしたいですね。
Google playでのベータ版配布機能について - Qiita

参考

OpenSSLの仕組みとは?初歩から解説! | Tech2GO
OpenSSLの説明

aarをローカルから読み込む

概要

aarをローカルから読み込む方法を知った(教えていただいた)ので、メモしときます。

🔍ちなみにaarとは
Android ARchiveの略です。
Androidリソースやマニフェストファイルを含めることのできるAndroidライブラリです。

作り方としては、[File] > [New] > [New Module] > [Android Library] > [Next] > 必要に応じて設定変更 > [Finish]で、{$project}/{$library_name}/build/outputs/aar/{$library_name}.aarができます。

対応方法

1. aarをモジュールのlibsディレクトリに置く

aarをドラッグ&ドロップで取り込めます。
初回にファイル形式を聞かたことが一度だけあります。aarがなくて困ったんですが、textを選んで問題なく進められました。

2. dirsにaarを探索するディレクトリをbuild.gradleからの相対パスで書く

{$module}/build.gradle

repositories {
    flatDir {
        dirs 'libs'
    }
}

3. nameに2からの相対パス、extに拡張子を書く

{$module}/build.gradle

dependencies {
    compile(name:'拡張子を除くaarファイル名', ext:'aar')
}

参考

Create an Android Library | Android Studio
aarの説明

Material Design 1.マテリアルデザインとは何か

同期のデザイナーの子にマテリアルデザインのことを聞かれた時、答えられなくて悔しかったのでw
公式ドキュメントを読みつつ、マテリアルデザインについてまとめていきたいと思います。(全10回くらいの予定)

デザインの歴史

スキューモーフィズムからマテリアルデザインに到るまでの流れを追っていきます。

スキューモーフィズム(1890年頃〜)

現実世界の視覚のルールをデザインに落とし込んだものです。

f:id:A_01:20170419233400p:plain 図1:スキューモーフィズムの例。紙のノートのような質感を持つ立体的なデザイン。

フラットデザイン(1920年頃〜)

装飾性を抑えたシンプルで平面的なデザインです。

f:id:A_01:20170419235107j:plain 図2:フラットデザインの例

こんなこと言うとなんですが、私は洗練されていて結構好きですw

メトロUI(2010年頃〜)

過剰な装飾を削ぎ落とした点において、フラットデザインの一種と言えます。
しかし、完全なフラットデザインではなく、もちろん完全なスキューモーフィズムでもなく、中間的な立ち位置(フラットデザイン寄り)です。

f:id:A_01:20170419235127p:plain 図3:メトロUIの例

マテリアルデザイン(2014年頃〜)

フラットデザイン及びメトロUIの持つ以下の課題を解決するものとして、マテリアルデザインが登場しました。

  • 立体的な表現をなくしたため、どこを押すことができるのか、あるいはどこに文字を入力できるのかわからない。
  • 無駄な装飾をなくしたため重要度が分かりづらい。

マテリアルデザインは

マテリアル(物質)のメタファー(比喩)

です。現実世界のルールをデザインに落とし込むことで、いつの時代でも、誰にでも、どんなデバイスでも通じるデザインを目指しています。
具体的には光と影、奥行きの概念を取り入れることで、現実世界の質量を表現し、直感的に分かりやすくしています。 ( →マテリアルは3D)

また、ユーザの操作に対しアニメーションで反応するなど触覚を大事にしている点でスキューモーフィズムと異なります。 (→意味のあるアニメーション)

マテリアル環境は3D

マテリアルデザインについて

「紙」と「インク」で構成されており、印刷物を意識した作り

という表現をよく見かけますが、つまり画面の縦横だけでなく、高さ(奥行き)も意識しているということです。

f:id:A_01:20170420000759j:plain 図4:x軸y軸に加えz軸が存在する

f:id:A_01:20170420000440j:plain 図5:パーツはそれぞれ3次元上に存在する。あるパーツがあるパーツを突き抜けるような現実にあり得ないデザインはない。

意味のあるアニメーション

ユーザの操作に対し、アニメーションでレスポンスを返すことによって、ユーザは自分の操作がどう伝わったのか、理解しやすくなります。

www.youtube.com 映像:マテリアルデザインの説明動画。「慣性」が意識されていることがよく分かる。

参考

エンジニアが武器にするMaterial Design // Speaker Deck
 ーエンジニアがマテリアルデザインを学ぶことの大切さが語られています。

マテリアル – 日本語
 ー公式ドキュメント。これは最低限読んでおくべきだと思います。(読んでいる途中だけどw)

マテリアルデザインについて少し調べる - Qiita
Googleマテリアルデザインとフラットデザインって結局何が違うの?[UI/UX] - NAVER まとめ
マテリアルデザインとは〜基本概念と実務で使える無料フレームワーク6選 |ferret [フェレット]
 ーマテリアルデザインって何?フラットデザインとどう違うの?という疑問に端的に答えてくれるサイトたちです。

Android オプションを付けてコンパイルする

概要

ビルド時にオプションを付けてコンパイルしてね,というエラーが出ました.

注意:一部の入力ファイルは非推奨のAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。

解決方法

buid.gradleを修正して再コンパイルすると詳細が見られます.

{$root}/buid.gradle

// ルートプロジェクトを含む全プロジェクトに適用
allprojects { 
    // 実行フェーズ開始前
    gradle.projectsEvaluated {
        // options.encoding = 'UTF-8'とかもこのちゅうかっこの中で指定できる
        tasks.withType(JavaCompile) {
            // オプション指定.uncheckedは未チェックなもの(*1),deprecationは非推奨なものを表示する
            options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
        }
    }
}

(*1)
こういう何の型が入るか定義されてないやつ.

ArrayList list = new ArrayList<>();

型チェックされたのはこういう状態.

ArrayList<Hoge> = new ArrraList<Hoge>();

参考