Androidのアプリ(apkファイル)を抽出して、証明書を確認する

Androidのアプリ(apkファイル)を抽出して、証明書を確認するメモ。

端末にインストールされているアプリ(apkファイル)を抽出する

Google Playでそのアプリのページを開き、URLからパッケージ名を確認します。
URLの「id=」に続く部分がパッケージ名になります。

https://play.google.com/store/apps/details?id=パッケージ名

パッケージ名を一覧表示

adb shell pm list packages -f

パッケージ名を絞り込んで表示

adb shell pm list packages -f | grep パッケージ名

「package:アプリの場所=パッケージ名」の形式で表示される

package:/data/app/~/base.apk=~

apkファイルを取り出す

C:\~\adb.exe pull /data/app/~/base.apk

証明書のfingerprintを表示する

keystoreから取り出す場合

keytool -list -keystore my-signing-key.keystore

apkから取り出す場合(Java7以上)

keytool -list -printcert -jarfile app.apk

Android Studio 2.1でJNIを使って開発するには

Android Studio 2.1でJNIを使って開発する手順です。

環境

  • Windows 10
  • Android Studio 2.1.1

プロジェクトの作成

Android Studioで新しいプロジェクトを作成します。

011

「Application name」と「Company Domain」を入力します。

ここでは、「Application name」を「JniTest」としました。

012

「Phone and Tablet」をチェックし、「Minimum SDK」を選択します。

013

「Empty Activity」を選択します。

014

「Activity Name」と「Layout Name」は初期値のままにします。

015

プロジェクトが作成されます。

016

メニューの「Run」→「Run ‘app’」を選択して、アプリケーションを実行できることを確認します。

017

018

Gradleの設定

メニューの「File」→「Settings」を選択し、「Build, Execution, Deployment」→「Build Tools」→「Gradle」を選択します。

「Use Default Gradle wrapper (recommended)」にチェックを入れ、「OK」ボタンを押します。

019

Android NDKのインストール

メニューの「Tools」→「Android」→「SDK Manager」を選択します。

「SDK Tools」タブを選択し、「Android NDK」をチェックします。。

001

「Apply」ボタンを押します。

002

License Agreement画面の「Accept」をチェックして、「Next」ボタンを押します

003

インストールが始まります。

004

メニューの「Run」→「Run ‘app’」を選択して、アプリケーションを実行できることを確認します。

build.gradle(Project)ファイルの編集

「build.gradle(Project: jnitest)」を開きます。

classpath 'com.android.tools.build:gradle:2.1.0'

の行を次のように変更します。

classpath 'com.android.tools.build:gradle-experimental:0.7.0'

020

gradle-wrapper.propertiesファイルの編集

「gradle-wrapper.properties (Gradle Version)」を開きます。

distributionUrl=…

の行を次のように変更します。

distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

021

build.gradle(Module)ファイルの編集

「build.gradle(Module: app)」を開きます。

次のように変更します。

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.3"

        defaultConfig {
            applicationId = "jp.gesource.jnitest"
            minSdkVersion.apiLevel = 19
            targetSdkVersion.apiLevel = 23
            versionCode = 1
            versionName = "1.0"
        }
        buildTypes {
            release {
                minifyEnabled = false
                proguardFiles.add(file('proguard-android.txt'))
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
}

メニューの「Run」→「Run ‘app’」を選択して、アプリケーションを実行できることを確認します。

Android NDK locaationの設定

「File」→「Project Structure」→「SDK Location」を選択します。

「Android NDK locaation」が設定されていなければ、設定して「OK」ボタンを押します。

022

build.gradleの設定

build.gradle(Module: app)を開き、「buildTypes」の設定の下に「ndk」の設定を追加します。

buildTypes {
    …
}
ndk {
    moduleName = "jnitest"
}

023

MainActivityの編集

MainActivity.javaを開き、次の行を追加します。

static {
    System.loadLibrary("jnitest");
}
public native String getMsgFromJni();

build.gradleのmoduleNameで設定した名前をSystem.loadLibraryの引数に設定します。

024

getMsgFromJni関数が存在しないため、getMsgFromJniの部分でエラーになっています。
カーソルをgetMsgFromJniの上に移動し、ALT+Enterキーを押します。

025

Enterキーを押すと、jniフォルダーにjnitest.cファイルが作成され、関数が作成されます。

#include <jni.h>

JNIEXPORT jstring JNICALL
Java_gesource_jp_jnitest_MainActivity_getMsgFromJni(JNIEnv *env, jobject instance) {
    // TODO
    return (*env)->NewStringUTF(env, returnValue);
}

jnitest.cのreturnValueの部分を編集します。

return (*env)->NewStringUTF(env, "Hello JNI");

res/layout/activity_main.xmlファイルを開き、TextViewのidを「jni_msgView」に設定します。

026

MainActivity.javaを開き、MainActivityクラスのonCreateメソッドの末尾に次の行を追加します。

((TextView) findViewById(R.id.jni_msgView)).setText(getMsgFromJni());

TextViewの部分がエラーになっているので、Alt+Enterキーを押して修正します。

027

メニューの「Run」→「Run ‘app’」を選択して、アプリケーションを実行できることを確認します。

028

C言語で記述した処理が実行されています。

近くにあるスマートフォンと接続・送受信するNearby API

Google Play サービス 7.8からNearby APIが追加されました。
このNearby APIを使うと、物理的に近くのデバイスとやりとりができます。

Nearby APIには2つのAPIがあります。

  • Nearby Messages API
  • Nearby Connections API

Nearby Messages API

ちょっとしたデータを隣の人に送るための簡単な方法が今までありませんでした。
送り先のメールアドレスやLineのアカウントを知る必要がありました。
このAPIがその問題を解決するかもしれません。

Nearby Messages APIは、Bluetooth、Wi-Fi、不可聴のサウンドを使用して、近くにあるデバイスを検出します。

不可聴のサウンドというのは、人には聞こえない周波数のようです。
端末によっては、聞こえる端末もあるようです。
若い人には聞こえやすいかもしれません。

データのやりとりはサーバーを介して行われます。
デバイスは同じネットワークに接続している必要はありませんが、ネットワークに接続している必要があります。

Nearby Messages APIは、AndroidだけでなくiOSにも対応しています。
AndroidとiOSの両方のOSで利用可能です。

Nearby Connections API

Nearby Connections APIは、ローカルネットワーク上の他のデバイスを検出し接続します。

Androidで顔検出APIが使えるようになった

Gppgle Play サービス 7.8から、Face APIを利用できるようになりました。
画像やカメラの映像から人の顔を検出ことができます。

顔検出を行うにはOpenCVのライブラリを使う必要がありました。
Google Play サービスで提供されるようになったので手軽に使用できます。

サンプルアプリケーション

サンプルアプリケーションはGitHubに公開されています。

photo-demoは、顔の画像から特徴点を検出するサンプルです。

face01

ソースコードを見てみます。

顔検出のためのインスタンスを作成します。

PhotoViewerActivityクラスのonCreateメソッドで検出しています。

静止画のため、setTrackingEnabledをfalseにします。
動画や連続した画像の時はtrueにします。

すべてのランドマークを検出するためにsetLandmarkTypeをALL_LANDMARKSに設定します。

FaceDetector detector = new FaceDetector.Builder(getApplicationContext())
        .setTrackingEnabled(false)
        .setLandmarkType(FaceDetector.ALL_LANDMARKS)
        .build();

SafeFaceDetectorを使うのは、非常に小さな画像上の顔検出のバグを回避するための処理とのこと。

Detector<Face> safeDetector = new SafeFaceDetector(detector);

画像からFrameを作成します。

Frame frame = new Frame.Builder().setBitmap(bitmap).build();

作成したFrameから顔検出処理を実行します。

SparseArray<Face> faces = safeDetector.detect(frame);

Faceクラスのインスタンスのコレクションを取得しました。
これをFaceViewクラスのdrawFaceAnnotationsメソッドで描画しています。

個々のFaceインスタンスの座標を取得して円を描画しています。

for (int i = 0; i < mFaces.size(); ++i) {
    Face face = mFaces.valueAt(i);
    for (Landmark landmark : face.getLandmarks()) {
        int cx = (int) (landmark.getPosition().x * scale);
        int cy = (int) (landmark.getPosition().y * scale);
        canvas.drawCircle(cx, cy, 10, paint);
    }
}

サンプルを少し変更して、笑顔の可能性を取得してみます。

FaceDetector detector = new FaceDetector.Builder(getApplicationContext())
        .setTrackingEnabled(false)
        .setLandmarkType(FaceDetector.ALL_LANDMARKS)
        .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
        .build();

Detector<Face> safeDetector = new SafeFaceDetector(detector);

Frame frame = new Frame.Builder().setBitmap(bitmap).build();
SparseArray<Face> faces = safeDetector.detect(frame);

if (faces.size() > 0) {
    String text =  "SmilingProbability: " + String.format("%.2f", faces.get(0).getIsSmilingProbability());
    Toast.makeText(this,text, Toast.LENGTH_LONG).show();
}

face02

「SmilingProbability: 0.59」と表示されました。
値は0.0から1.0の間を取るようです。
やや笑顔かな、といったところでしょうか。

サンプルアプリケーションは他に、「FaceTracker」と、「multi-tracker」があります。
カメラの映像から認識するサンプルです。