Android アプリ開発時の Intellij IDEA の設定

EAPでも厳しい感じするのですが...。

一応、ビルド→ラウンチはできるけど。

右下にアラートが出る。

開くと以下ダイアログ。


Unexpected schema version 3
java.lang.AssertionError: Unexpected schema version 3
	at com.android.dvlib.DeviceSchema.getXsdStream(DeviceSchema.java:247)
	at com.android.dvlib.DeviceSchema.getSchema(DeviceSchema.java:331)
	at com.android.sdklib.devices.DeviceParser.getParser(DeviceParser.java:503)
	at com.android.sdklib.devices.DeviceParser.parseImpl(DeviceParser.java:489)
	at com.android.sdklib.devices.DeviceParser.parse(DeviceParser.java:464)
	at com.android.sdklib.devices.DeviceManager.initUserDevices(DeviceManager.java:444)
	at com.android.sdklib.devices.DeviceManager.initDevicesLists(DeviceManager.java:287)
	at com.android.sdklib.devices.DeviceManager.getDevice(DeviceManager.java:217)
	at com.android.sdklib.internal.avd.AvdManager.parseAvdInfo(AvdManager.java:1486)
	at com.android.sdklib.internal.avd.AvdManager.buildAvdList(AvdManager.java:1382)
	at com.android.sdklib.internal.avd.AvdManager.<init>(AvdManager.java:358)
	at com.android.sdklib.internal.avd.AvdManager.getInstance(AvdManager.java:403)
	at com.android.tools.idea.avdmanager.AvdManagerConnection.initIfNecessary(AvdManagerConnection.java:170)
	at com.android.tools.idea.avdmanager.AvdManagerConnection.getAvds(AvdManagerConnection.java:277)
	at com.android.tools.idea.run.editor.DevicePicker.lambda$refreshAvds$2(DevicePicker.java:186)
	at com.intellij.openapi.application.impl.ApplicationImpl$1.run(ApplicationImpl.java:315)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

想像できるのは、android コマンドが利用できなくなったこと。2017年8月ぐらいからか。


$ ./android
*************************************************************************
The "android" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager
*************************************************************************

現在、最新版の 2017.3.3 なのですが。

GradleのバージョンやAndroidプラグインのバージョンなどに強く依存して頻繁な更新の影響を受けてるわけで。


This Gradle plugin requires a newer IDE able to request IDE model level 3. For Android Studio this means version 3.0+


$ adb push /projects/ExampleApp/app/build/outputs/apk/debug/app-debug.apk /data/local/tmp/com.example.app
$ adb shell pm install -r "/data/local/tmp/com.example.app"
Failure [INSTALL_FAILED_TEST_ONLY: installPackageLI]

$ adb shell pm uninstall com.example.app
Unknown failure (at android.os.Binder.execTransact(Binder.java:565))
Error while Installing APK

ある程度の対応策としては以下はあるが。


# gradle.properties
android.injected.build.model.only.versioned=3
android.injected.testOnly=false

とうとうGUI制限が入った Android Studio 3.0 Beta4 - exception think

環境だけでで振り回される外の人々。

中の人たちはそれなりの設定方法があるのだろうか。


FCM と Notification の併用をやめてバックグラウンド受信時にうれしがる

ややこしすぎな気がします。

この記事のタイトルも書いてて意味不明です。

以下のような、FCMにJSONをPOSTしてアプリで受ける場合の話です。


curl https://fcm.googleapis.com/fcm/send -X POST \
--header "Authorization: key=FirebaseConsoleのプロジェクトの設定、クラウドメッセージングのタブにあるサーバーキー" \
--Header "Content-Type: application/json" \
 -d '
 {
   "to":"/topics/all",
   "data":{
     "title":"New Notification!",
     "body":"Test"
   },
   "priority":"high"
 }'

このPOSTするJSONに含まれるデータ構造によって、アプリ側で受信する場合の処理の流れ変わって見通しが悪くなります。

きれいにまとめられています。

Firebase Notificationでアプリの状態による挙動の違いについて - Qiita

アプリがフォアグラウンドにある場合、このServiceのonMessageReceived()が呼び出されることになります。

アプリがバックグラウンドにある場合はこのonMessageReceived()は呼ばれることはなく、システム側で自動的にシステムトレイに通知を表示します。

"data"ブロックはConsoleからも含めることはできます(詳細オプションのカスタムデータで指定できる)。しかし、Consoleでは"notification"ブロックを省略することができません(メッセージ文を入力しないと送信できない)。

送信したメッセージに"data"ブロックがあっても、"notification"ブロックが存在する限り、アプリがバックグラウンドにある状態ではFirebaseMessagingServiceのonMessageReceived()は呼ばれません。

"data"ブロックの内容を受け取れないわけではありません。通知をクリックして起動したActivityのintentに含まれることになります。

"data"ブロックの内容の処理が、フォアグラウンド時に受け取ったときはFirebaseMessagingServiceで、バックグラウンドのときにはActivityでとなってしまって煩雑です。

実際に試してみると、これら書かれてることすごく良く分かります。

結局、この"notification"ブロックの特典としては、

アプリがバックグラウンド状態で受信した場合にのみ、アプリ側の実装なしで通知トレイに入る。

ということだけでしょうか、おおまかですが。

すべてのメッセージ受信時にonMessageReceived()が呼び出されれば、アプリがフォアグラウンドにあるかバックグラウンドにあるかを気にする必要がなくなります。

なるほど。

では、入れ子にしたらいいんじゃないかと。

例えば、


{
  // ...

  "notification": {
    "title" : "News!!",
    "body" : "New Product Release!!"
  },

  "data": {
    "user": "Yamada Taro",
    "age": 20
  },

  // ...
}

を以下のように入れ子にする。


{
  // ...

  "data": {
    "user": "Yamada Taro",
    "age": 20,

    "notification": {
      "title" : "News!!",
      "body" : "New Product Release!!"
    }

  },

  // ...
}

すべてサービスで受けることができます。


class  MyFirebaseMessagingService : FirebaseMessagingService() {

  override fun onMessageReceived(message: RemoteMessage) {

    // ...

    // 2層目以下はStringで送られてくるのでMap化
    message.data["notification"]?.let {
      val notification : Map<String, String> =
        Gson().fromJson(it, object : TypeToken<HashMap<String, String>>() {}.type)
      sendNotification(notification)
    }

  }

  // サンプルを参考に
  private fun sendNotification(notification: Map<String, String>) {
    val intent = Intent(this, MainActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

    val pendingIntent = PendingIntent.getActivity(this, 0, intent,
        PendingIntent.FLAG_ONE_SHOT)

    val channelId = getString(R.string.default_notification_channel_id)
    val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
    val notificationBuilder = NotificationCompat.Builder(this, channelId)
        .setSmallIcon(android.R.drawable.ic_notification_overlay)
        .setContentTitle(notification["title"])
        .setContentText(notification["body"])
        .setAutoCancel(true)
        .setSound(defaultSoundUri)
        .setContentIntent(pendingIntent)

    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    notificationManager.notify(0, notificationBuilder.build())
  }

quickstart-android/MyFirebaseMessagingService.java at master · firebase/quickstart-android

元々、Firebase てのは、敷居を下げてマーケティングなどに利用を広めようとしてるのかな。


Amazon vs Google の排除合戦に Apple が参入した?

ネットの中立性があやしくなってきていますが。

米、「ネットの中立性」撤廃 コンテンツの扱い格差容認 (写真=AP) :日本経済新聞

Net Neutrality - Bloomberg

で、最近のニュース。

GoogleはEcho Show向けにAmazonが用意したYouTubeアプリがGoogleの利用規約に違反しているとして、Echo ShowでYouTubeを使えないようにしました。その直後、AmazonはGoogle系列のスマートホーム企業Nestの一部製品をAmazonで販売停止にして対抗します。

AmazonとGoogleのバトルが激化 ユーザー不在の締め出し合戦へ - ITmedia PC USER

そんなことを考えながら、

ADBをアップデートして少しビビる、今日。

ビルドツールを更新すると、OS X上でADBが動作しなくなる

Updating to build tools 27.0.2 breaks ADB on OS X : androiddev


$ cd $ANDROID_SDK_ROOT
$ rm -r platform-tools/
$ curl https://dl.google.com/android/repository/platform-tools_r26.0.2-darwin.zip -o platform-tools_r26.0.2-darwin.zip
$ unzip platform-tools_r26.0.2-darwin.zip

iPhone の Apple をGoogleの敵と単純に考えてしまってはいけませんね。

すいません。


関連ワード:  AndroidGoogle速報開発