20190820のAndroidに関する記事は5件です。

Androidアプリにも審査がされるようになった件

先日Androidアプリをリリースしようといつもどおりの作業を行ったのですが、5時間たっても公開されない状況が続いていたため、なにかあったのかと思いコンソールを見てみると、初めて見るメッセージが表示されていました。

image.png

「Androidアプリに審査…?公開後に機械的にやってるんじゃないの…?」
と思ったのですが、Twitterなどで調べてみると、Androidアプリの審査があってアプリが公開できていないという話をされてる方がちらほらいました。

とりあえずこちらでは制御できないので、一旦審査が終わるのを待ちました。
翌朝確認してみるとストアにアプリが公開されており、「アップデート公開したよ!」というメールが深夜3時頃に来ていました。
リリース作業を行ったのが14時頃だったので、リリースまでに13時間ほどかかったことになります。

とりあえずリリースは無事終わったのですが、改めて審査についてGoogleに問い合わせしてみました。

Q. 審査って何時間ぐらいかかりますか?
A. 目安としては、最大48時間です。

Q. 審査って土日もやっているのですか?
A. 審査は営業日に行うので、土日を挟むと審査が遅れる可能性があります。

Q. 審査を先に通過させておくなど、デベロッパー側でリリースタイミングを制御する方法はありますか?
A. 時間指定公開を使えばデベロッパー側で制御できます。 しかし、時間指定公開は、すでに公開されているアプリのアップデートをリリースする場合のみ有効で、新規に公開するアプリは使用できません。

8/22 追記
新規アプリの時間指定公開についてですが、@kafumi さんからコメントで、新規に公開するアプリを時間指定公開する方法があるとのご指摘をいただいたので訂正します。

クローズドトラックに一度公開し、そちらから製品版にプロモートする形であれば時間指定公開を利用できるとのことで、新規アプリでもこの方法を使えばリリースタイミングが制御できるようです。

Q. 審査でリジェクトされる可能性ありますか?ある場合、リジェクトの基準などありますか?
A. 社内ポリシーのためお答えできません。参考にこちらをご確認ください。

とのことでした。

今後のリリースについて

審査が入ること自体はGoogle Play Storeが無法地帯にならないので良いことだと思うのですが、審査を土日にやってくれないのはなかなかタイミングが難しいですね…

深夜3時にアップデートが公開されたことから、審査はカリフォルニアで行っているようです。
なので、日本時間の金曜日に提出した場合、その日のうちに審査が通る可能性もあると思われます。
同時に、アメリカの祝日についても考慮しなければいけないですが…

今後は、Androidアプリのリリースも審査があることを考慮してリリーススケジュールを組む必要がありそうです。
リリースのタイミングをデベロッパー側でなるべく制御したい場合は、時間指定公開を有効にし、先に審査を通過させておく必要があります。

時間指定公開のやり方は、以下のページに記載があります。
https://support.google.com/googleplay/android-developer/answer/6334282?hl=ja

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Androidで色の透過率を指定する

Color.argbで指定する方法

example.kt
import android.graphics.Color

Color.argb(128, 51, 51, 51)

引数として以下の4つの値を10進数(0〜255)のintで渡す。

  • alpha 透過率
  • red 赤
  • green 緑
  • blue 青

↑の例の場合、以下のような値を渡している。

  • alpha = 128
  • red = 51
  • green = 51
  • blue = 51

colors.xmlで定義する方法

app_name/app/src/main/res/values/colors.xml
<color name="example">#80333333</color>

2桁ごとに以下の4つの値を16進数(0〜FF)で指定する。

  • alpha 透過率
  • red 赤
  • green 緑
  • blue 青

↑の例の場合、以下のような値を定義している。

  • alpha = 80
  • red = 33
  • green = 33
  • blue = 33
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Androidで色の透過率を指定する

Color.argbで指定する方法

example.kt
import android.graphics.Color

Color.argb(128, 51, 51, 51)

引数として以下の4つの値を10進数(0〜255)のintで渡す。

  • alpha 透過率
  • red 赤
  • green 緑
  • blue 青

colors.xmlで定義する方法

app_name/app/src/main/res/values/colors.xml
<color name="example">#80333333</color>

2桁ごとに以下の4つの値を16進数(0〜FF)で指定する。

↑の例の場合、
alpha = 80
red = 33
green = 33
blue = 33

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Roomで多対多のEntityを取得する方法

はじめに

みなさんRoom使っていますか?
SQLiteの面倒な部分をいい感じにやってくれるいいヤツです。

多対多な関係にあるEntityの取得方法に苦戦にしていたところ
最高の解決方法があったのでシェアします。

多対多(Many-to-Many)の関係

多対多の関係とはなんぞや?知っている方はスキップで大丈夫です。

簡単に言えば、音楽のプレイリストと楽曲の関係と同じです。

例えば、「新海誠」というプレイリストに

  • 「前前前世/RADWIMPS」
  • 「愛にできることはまだあるかい/RADWIMPS」
  • 「One more time, One more chance/山崎まさよし」
  • 「Rain/秦基博」

という複数の楽曲が登録されているとします。

一方で、「RADWIMPSマイベスト」というプレイリストには

  • 「前前前世/RADWIMPS」
  • 「愛にできることはまだあるかい/RADWIMPS」
  • 「おしゃかしゃま/RADWIMPS」

という複数の楽曲が登録されているとします。

「新海誠」と「RADWIMPSマイベスト」には共通して

  • 「前前前世/RADWIMPS」
  • 「愛にできることはまだあるかい/RADWIMPS」

という楽曲があることが分かります。

このように、一つのプレイリストに対して複数の楽曲が紐付いていて、一つの楽曲に対しても複数のプレイリストに紐付いているような関係を多対多と呼びます。

本題

Roomを使ってこの関係を表現しようとすると、

@Entity
data class PlayList(
    @PrimaryKey val id: Long,
    val name: String
)

@Entity
data class Song(
    @PrimaryKey val id: Long,
    val name: String
)

@Entity(
    primaryKeys = ["play_list_id", "song_id"],
    foreignKeys = [
        ForeignKey(
            entity = PlayList::class,
            parentColumns = arrayOf("id"),
            childColumns = arrayOf("play_list_id")
        ),
        ForeignKey(
            entity = Song::class,
            parentColumns = arrayOf("id"),
            childColumns = arrayOf("song_id")
        )
    ]
)
data class PlayListAndSongXRef(
    @ColumnInfo(name = "play_list_id")
    val playListId: Long,
    @ColumnInfo(name = "song_id")
    val SongId: Long,
)

のようにプレイリストと楽曲の関係を表す中間テーブルを用意して実現すると思います。
(Songクラスには簡単のためにアーティスト名は省略)

では、特定のプレイリストとそのプレイリストに紐づく楽曲一覧を取得したいとしましょう。
以下のようなEntityとして返ってくることを期待しています

data class PlayListAndSongs(
    val playList: PlayList,
    val songs: List<Song>
)

これをDao経由で一発で取得する方法が分からず、頭を悩ませていましたが
Room2.2-alpha01から@Junctionというアノテーションが追加され、

https://developer.android.com/jetpack/androidx/releases/room#2.2.0-alpha01

試しに使ってみたらいともたやすく解決できてしまいました。

@Junctionアノテーションは、今回のような中間テーブル経由で紐づく複数のデータを取得する際に利用することができます。

使い方は簡単です。

class PlayListAndSongs {
    @Embedded
    lateinit var playList: PlayList // ①

    @Relation(
        entity = Song::class, // ②
        parentColumn = "id", // ③
        entityColumn = "id", // ④
        associateBy = Junction(
            value = PlayListAndSongXRef::class, // ⑤
            parentColumn = "play_list_id", // ⑥ 
            entityColumn = "song_id" // ⑦
        )
    )
    lateinit var songs: List<Song>
}

①:@Embeddedアノテーションを取得する親になるフィールドに付与します。
②:@Relationアノテーションを複数の子になるフィールドに付与して、entityに子のクラスを指定します。
parentColumn@Embeddedを付与したクラス(PlayList)と中間テーブル(PlayListAndSongXRef)を紐付けるためのPlayList側のキー
entityColumnSongと中間テーブルを紐付けるためのSong側のキー

※③、④のカラム名が同じでややこしくなってしまった・・・。

⑤: associateByにはvalueに中間テーブルのクラス、
parentColumn@Embeddedを付与したクラス(PlayList)と中間テーブル(PlayListAndSongXRef)を紐付けるための中間テーブル側のキー
entityColumnSongと中間テーブルを紐付けるための中間テーブル側のキー

を指定します。

あとはDaoを

@Dao
interface PlayListAndSongsDao {
    @Query("""
        SELECT *
        FROM PlayList
        WHERE name = :name
        LIMIT 1
    """)
    fun getPlayListAndSongsByName(name: String): PlayListAndSongs
}

のように定義して、

val playListAndSongs = dao.getPlayListAndSongsByName("新海誠")

とすれば「新海誠」のプレイリストとそれに紐づく複数の楽曲データがリストで取得できます。

@Junction すげー!

2019/8/20段階ではalphaな機能なのでプロダクションで使うには検討が必要ですが、他対他のデータ取得がとても簡単になるので、
ぜひ導入していきたいですね。
自分は個人開発アプリでガシガシ使っていこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

androguardを使ってapkを解体する

androguardというツールを使ってapkを解体してみる。
どのへんがガードなんだ逆じゃないか、と言いたくなるのは置いておくとして。

TL;DR

pip3 install -U androguard[magic,GUI]
androguard analyze TestActivity.apk
In [2]: dx.classes
:
In [3]: for meth in dx.classes['Ltests/androguard/TestActivity;'].get_methods():
    print("inside method {}".format(meth.name))
    for _, call, _ in meth.get_xref_to():
        print("  calling -> {} -- {}".format(call.class_name, call.name))
androguard axml TestActivity.apk
androguard arsc TestActivity.apk --list-types
androguard arsc TestActivity.apk --type string --locale ja
androguard axml TestActivity.apk -r res/layout/main.xml

環境

  • MacOS Mojave 10.14.6(18G87)
  • Python 3.7.4
  • Androguard version 3.3.5

androguard の導入

以下を実行。

pip3 install -U androguard[magic,GUI]

apkの中身を見る

以下を実行。

androguard analyze TestActivity.apk

すると In [1]:のような表示が出るので、そこで dx.classes してみる。
するとすべてのクラスの一覧が表示される。

次に a.get_activities() してみる。
するとapkに含まれるすべてのアクティビティのクラスが列挙される。

その他、以下のようなコマンドが実行できる。

In [4]: a.get_package()
Out[4]: 'com.greenaddress.abcore'

In [5]: a.get_app_name()
Out[5]: u'ABCore'

In [6]: a.get_app_icon()
Out[6]: u'res/mipmap-xxxhdpi-v4/ic_launcher.png'

In [7]: a.get_androidversion_code()
Out[7]: '2162'

In [8]: a.get_androidversion_name()
Out[8]: '0.62'

In [9]: a.get_min_sdk_version()
Out[9]: '21'

In [10]: a.get_max_sdk_version()

In [11]: a.get_target_sdk_version()
Out[11]: '27'

In [12]: a.get_effective_target_sdk_version()
Out[12]: 27

コマンドラインは通常通り、 Ctrl+D で抜ける事ができる。

AndroidManifest.xml を読む

以下コマンドを実行するだけ。

androguard axml TestActivity.apk

res(リソース)を一覧する

# 種類を一覧する
androguard arsc TestActivity.apk --list-types

# 色を一覧する
androguard arsc TestActivity.apk --type color

# 日本語リソースの文字列を一覧する
androguard arsc TestActivity.apk --type string --locale ja

layoutを読む

下記のようなコマンドで解体できる。

androguard axml TestActivity.apk -r res/layout/main.xml

リソースは探すのが手間なので、拡張子を apk から zip に変更して解凍し、バイナリXMLにしてからandroguardしたほうが楽。

ただし、これで出てくるのはリソースのIDの状態なので、例えば android:id="@7F0802F9" という値があるとして、 R.java から 0x7f0802f9 になっている値を探して、それが hoge_id だと判明する。色や文字列の場合は、そこから更に --type color などで追いかける必要があって結構難儀。

備考

androlyze.py はどうやら動かない。
プログラムを解体したいだけなら、 jaddex2jar を組み合わせたほうが楽。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む