Google Playで成功するためのベストプラクティス

という記事がある。これは1ヶ月ほど前にTechCrunchに寄稿された

と同じ著者による記事の翻訳になっている。


持ち出しているデータや論調は同じような物なのだが、Google Playで公開するときにアプリのタイトルや説明文の書き方で注意すべき点が抜けているので、その部分だけ軽く訳しておく。


いつもの技術系記事と違ってマーケティングのお話なのでよく分からずに訳しているところもあり、おかしな所があれば指摘いただきたい。

ベストプラクティス

o アプリのタイトルの検索性を最大化する

もっとも成功したキーワードを特定して、アプリのタイトルに確実に含めておく。実際、成功するためにこれはとても重要で(検索ランキングで80から100の順位に影響する可能性がある)、タイトルからはアプリ名を外して一番重要なキーワードの説明に注力することを真剣に検討すべきだ。アプリの説明にアプリ名を含めておけば、ユーザは名前で検索することもできる。iOSと違い、Google Playではアプリ説明文も検索される。

o キーワードを適度に使い、そして使い過ぎない

アプリ説明文にキーワードを5回含めるようにする。検索ランキングで10から20の順位に影響する。5回以上書いてもそれ以上の効果はないので、使い過ぎないようにする。

o 検索パラメータをテストする

上記のオススメはこれまでの経験に基づいたガイドラインだ。しかし、検索結果は多くの要因で変動する。

o 持続こそ力

Google Playのランキングアルゴリズムは長期的なユーザ獲得に向けられている。新規ユーザを獲得してそのユーザを長く満足し続けられるアプリはより高い順位がもたらされるアルゴリズムだ。広告は長期間に渡ってキャンペーンし続け、2,3ヶ月持続するべきだ。iOSマーケットでよく見られる、短期間のバースト広告とは逆だ。

o 閉回路マーケティングを使い、長期ユーザをターゲットとする

固定客がランキングに与える影響が大きいので、ユーザの認識率を上げ、上客をもたらす広告ソースを活用する、閉回路マーケティングを用いる。

o Try

Androidではマーケットで独自の方針を実験したりテストしたりすることを恐れる必要はない。また、Androidマーケットで得られた知見をiOSバージョンに反映して、コストとリスクを減らすことも出来る。


o 訳注
アプリのtitle/name/descriptionに関する説明がないので、以下のように想定している。
title: タイトル(例 みんなのラーメンタイマー)
name: パッケージ名(例 com.androidtsubu.ramentimer)
description: 説明文(例 カップラーメンのバーコードを読み込むだけでラーメンの茹で時間がわかります。)


記事中の「固定客を満足させ続けるとランキングが上がる」というのは、先日東海GTUGで行われた

でQ&Aのあった「Google Playでfeaturedされるアプリの条件は?」に通じるところがあり、恐らくもっとも重視されているパラメータなのだろう。


で、closed loop marketingって何よ?

TF201をICS 4.0.3にアップデート

ASUS タブレットパソコン Eee Pad TF201 TF201-GD64D

ASUS タブレットパソコン Eee Pad TF201 TF201-GD64D

個人的に初ICS製品になった。アップデートファイルは30MB程度で思ったより小さい。早速、ログをチャキチャキとってGitHubに上げておいた。

  • CPUモードの切り替え
スクリプト 設定方法 Max
cpu1.sh 省電力モード 800MHz
cpu2.sh バランスモード 1GHz
cpu3.sh ノーマルモード 1.2GHz
cpu4.sh 手動 1.5GHz
cpu5.sh 手動 1.6GHz
  • cpu5.sh時のAnTuTuスコアは13,158
    • 1.8GHzオーバークロックしてる人柱は14,000超え
    • cpu3.sh時は10,000ちょっとなのでHoneycombと差はない
  • Honeycombより/systemは小さい
Honeycomb 470MB
ICS 467MB
  • featuresハイライト
    • feature:android.hardware.sensor.proximity
      • Honeycombには無かった近接センサー
  • .configハイライト
    • # CONFIG_ENABLE_DEFAULT_TRACERS is not set
      • DS-5は出来なさそう
    • CONFIG_NFC_DEVICES=y
    • CONFIG_USB_SERIAL_PL2303=y
      • シリアルコンソールに出来る?

HoneycombからIce Cream Sandwichになったからと言って、使用感は驚くほど変わらないw 強いて上げるとすれば、

  • USB Ethernet接続時に「Ether port is detected」とメッセージが出るようになった。
  • Chrome betaが使えた。
  • Cameraのシャッター音が無音化。
  • アップデートでsuが0755される。


相変わらずGPSはまったくつかみません。

Androidの行数

現在のmainリポジトリ

$ find . -name "*.[chS]" -o -name "*.cpp" -type f -print0 \
 | xargs -0 -l wc | awk '{sum += $1} END {print sum}'
4264143

$ find . -name "*.java" -type f -print0\
 | xargs -0 -l wc | awk '{sum += $1} END {print sum}'
5335869

960万行。


最初の頃は770万行*1だった。


そんなけ。

TF201でARM DS-5

2011/11末にARMのDeveloper Studio 5のCommunity Editionという無料版が公開された。TF201ではoprofileが有効化されているので、DS-5のStreamlineプロファイリングが出来るのではと淡く期待して作業してみた。


結論から言うと、出来なかった。Bootloaderのunlockソフトウェアも公開された*1ことだし、今後に期待してメモだけ残しておく。


まず、Ubuntuの32bit環境を用意する。64bit版では「filter is not applicable」というエラーが出てインストールが出来ない。Virtual BoxにUbuntuを普通にインストールして、Android SDKとNDKを普通にインストールして、DS-5を普通にインストールするだけ。


DS-5をインストールすると、Eclipseをインストールしたディレクトリの下に、

 $ ls plugins/com.arm.ds.collateral_5.8.0.20111129_133554/arm/gator/
 README_Streamline.txt  annotate/  daemon-src/  driver-src/  hrtimer_module/

というファイルがダウンロードされている。詳細な説明はREADMEに書かれているので一読する。


driver-src以下のソースコードをビルドして、カーネルモジュールを作る必要がある。従って、TF201のカーネルソースコードが必要になる。


ソースコードASUSダウンロードサイト*2NVIDIAのgitからダウンロード出来る。NVIDIAのgitは

 $ git clone git://nv-tegra.nvidia.com/linux-2.6.git

今回はASUSのサイトからダウンロードしたカーネルソースコードを使ったが、そのままではビルド出来なかった。

 $ cd kernel-3b434ee
 $ export ARCH=arm
 $ export PATH=/opt/arm-cc/bin:$PATH
 $ export CROSS_COMPILE=arm-none-linux-gnueabi-
 $ make tegra_cardhu_android_defconfig
 $ make zImage -j16
 arch/arm/mach-tegra/tegra3_tsensor.c:24: fatal error:
 devices.h: No such file or directory

tegra_cardhu_android_defconfigが実機のconfig.gzと同等であることは、.configと保存してあるconfig.gzとのdiffで確認した。ヘッダが足りないらしいので、

$ find . -name "devices.h"
./arch/arm/mach-tegra/devices.h
./arch/arm/mach-mx3/devices.h
./arch/arm/mach-ks8695/include/mach/devices.h
./arch/arm/mach-mmp/include/mach/devices.h
./arch/arm/mach-mx25/devices.h
./arch/arm/mach-cns3xxx/devices.h
./arch/arm/mach-ux500/include/mach/devices.h
./arch/arm/mach-mx5/devices.h
./arch/arm/mach-pxa/devices.h
./arch/arm/mach-imx/devices.h
./arch/arm/mach-msm/devices.h
./arch/arm/mach-mxc91231/devices.h
./include/config/misc/devices.h
./include/config/usb/announce/new/devices.h

mach-tegraにそれらしいのがあるので、arm/includeにコピーしておく。

 $ cp arch/arm/mach-tegra/devices.h arch/arm/include/
 $ make zImage -j16

今度は正常にビルド出来るので、READMEにあるように、

 $ cd gator-driver
 $ make -C /path/to/kernel-3b434ee M=`pwd` modules

これでgator.koが出来る。なんとかしてTF201に持って行き、

 $ su
 # insmod ./gator.ko
 insmod: init_module './gator.ko' failed (No such file or directory)

 # busybox insmod ./gator.ko
 insmod: can't insert './gator.ko': unknown symbol in module or invalid parameter

というわけでインストール出来ない。実は試す前から多分ダメだろうなと察しがついていた。READMEに詳細なカーネルコンフィギュレーションが書かれている。

Required Kernel Changes (depending on the kernel version, the location of these 
configuration settings within menuconfig may be different)
 - General Setup
  - [*] Profiling Support
 - Kernel hacking
  - [*] Tracers
    - [*] Trace process context switches and events
 - Kernel Features
  - [*] High Resolution Timer Support
  - [*] Use local timer interrupts (only required for SMP)

Kernel hackingの「Trace process context switches and events」がtegra_cardhu_android_defconfigではオフになっている。これをオンにしないと、実際にtraceデータを吐くモジュールがリンクされない。オンにして、DS-5 Readyなdefconfigとして保存して終了。

 $ make menuconfig
 $ make savedefconfig
 $ mv defconfig arch/arm/configs/tegra_cardhu_android_ds-5_defconfig


というわけで、無駄骨の複雑骨折でした。

*1:ただしICS専用なので国内版はまだunlock出来ない

*2:サイトが落てるので後日追記

Transformer Primeで有線LAN

dmesgを見ていたらUSB Hostモジュールとして

<6>[    8.162292] usbcore: registered new interface driver asix

が登録されていた。USBイーサの石。ということで、ビックカメラで下記を購入。



早速、家に帰ってつないでみたら、dmesgに

<6>[  100.845783] tegra_usb_resume+
<6>[  100.889849] tegra_usb_resume-
<6>[  101.181095] usb 1-1.2: new high speed USB device using tegra-ehci and address 3
<6>[  101.241086] usb 1-1.2: New USB device found, idVendor=0b95, idProduct=7720
<6>[  101.242163] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
<6>[  101.242764] usb 1-1.2: Product: AX88772 
<6>[  101.243787] usb 1-1.2: Manufacturer: ASIX Elec. Corp.
<6>[  101.244357] usb 1-1.2: SerialNumber: 556D27
<6>[  102.133280] asix 1-1.2:1.0: eth0: register 'asix' at usb-tegra-ehci.2-1.2, ASIX AX88772 USB 2.0 Ethernet, 4c:e6:76:xx:xx:xx
<6>[  102.184767] eth0: link down
<6>[  102.190679] ADDRCONF(NETDEV_UP): eth0: link is not ready
<6>[  103.795184] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
<6>[  103.807939] eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1


logcatに

D/ConnectivityService(  177): ConnectivityChange for ETHERNET: CONNECTED/CONNECTED
D/ConnectivityService(  177): Setting TCP values: [4095,87380,110208,4096,16384,110208] which comes from [net.tcp.buffersize.wifi]
D/ConnectivityService(  177): adding dns /192.168.62.200 for ETHERNET
D/ConnectivityService(  177): adding dns /8.8.8.8 for ETHERNET
D/ConnectivityService(  177): changing default proxy to 
D/ConnectivityService(  177): sending Proxy Broadcast for 
D/ConnectivityService(  177): addDefaultRoute for ETHERNET (eth0), GatewayAddr=192.168.62.200
D/Tethering(  177): Tethering got CONNECTIVITY_ACTION
D/Tethering(  177): MasterInitialState.processMessage what=3
V/TweetDeck(  771): ETHERNET CONNECTION UP
I/MediaUploader(  820): No need to wake up
D/GTalkService(  352): [ReonnectMgr] ### report Inet condition: status=false, networkType=9
I/ActivityManager(  177): Start proc com.asus.cm for broadcast com.asus.cm/.push.PushControlReceiver: pid=950 uid=1000 gids={3003, 1015, 3002, 3001}
D/ConnectivityService(  177): reportNetworkCondition(9, 0)
D/ConnectivityService(  177): Inet connectivity change, net=9, condition=0,mActiveDefaultNetwork=9
D/ConnectivityService(  177): starting a change hold
D/GTalkService(  352): [RawStanzaProvidersMgr] ##### searchProvidersFromIntent
D/CMC->CMConfig(  950): DMConfig.init()
D/CMC->CMConfig(  950): mFumoHandlerName=DefaultFumoHandler
D/GTalkService(  352): [ReonnectMgr] ### report Inet condition: status=false, networkType=9
D/ConnectivityService(  177): reportNetworkCondition(9, 0)
D/ConnectivityService(  177): Inet connectivity change, net=9, condition=0,mActiveDefaultNetwork=9
D/ConnectivityService(  177): currently in hold - not setting new end evt


netcfgの結果は

$ netcfg
lo       UP                                   127.0.0.1/8   0x00000049 00:00:00:00:00:00
dummy0   DOWN                                   0.0.0.0/0   0x00000082 aa:02:9a:xx:xx:xx
usb0     DOWN                                   0.0.0.0/0   0x00001002 62:80:3d:xx:xx:xx
sit0     DOWN                                   0.0.0.0/0   0x00000080 00:00:00:00:00:00
ip6tnl0  DOWN                                   0.0.0.0/0   0x00000080 00:00:00:00:00:00
wlan0    UP                                     0.0.0.0/0   0x00001003 c8:60:00:xx:xx:xx
eth0     UP                                192.168.62.3/24  0x00001043 4c:e6:76:xx:xx:xx


ブラウザやマーケットも有線LAN経由でアクセス出来る。ConnectivityManagerに手を入れないと、マーケットは「ネットワークの回復を待っています」というダイアログが出て使えないと思っていたのだが、いつの間にか TYPE_ETHERNET としてイーサネットのサポートが入っていた。 ConnectivityManager.TYPE_ETHERNET のようなフレームワークで使用されている。ethデバイスが追加されるとDHCPなどの面倒を見てくれるようだ。root権限は不要。


有線LANでも使えると嬉しい人も中には居るのではなかろうか。ただし、 ro.sercure=1 かつ ro.debuggable=0 なので、充電しつつLAN経由でのadb接続は残念ながら出来ない。またTetheringデバイスからeth0が除外されているので、簡易WiFiルータとしても使えない。


モジュールがカーネルにスタティックリンクされているせいか、一度接続してからUSBアダプタを抜いて再接続すると、リブートするまでイーサネットに接続できなくなる。ここは認識が間違っていた。


ueventでUSBイーサの接続を検出しているので、/initが終了していないとUSBイーサを発見しない。電源ONする時はUSBイーサを抜いておいて、完全に起動してからUSBイーサを接続する。その後は抜き差ししても正常につながる。

Transformer Primeのマルチコアとクロック

ASUS タブレットパソコン Eee Pad TF201 TF201-GD64D

ASUS タブレットパソコン Eee Pad TF201 TF201-GD64D


Tegra 3初物ということで、発売日に購入。とある勉強会でUstream用に購入当日にまさかの実戦投入。勉強会を始めてから2時間程して、電源つないでいるのになぜか電池がきれそうになり、よく見たらちゃんとタブレットとキーボードが接続されていなかった。というか、タブレット側の電池だけで2時間もUstream出来たのが驚き。


4コアということで、コアがどんなクロックで推移するのか気になったので、CPUクロックを3秒ごとにprintfするCプログラムを書いて眺めてみた。そのまとめ。

  • GovernorはInteractive
  • 設定可能なクロックは102MHzから1.4GHz
    • 102 204 370 475 620 760 880 1000 1100 1200 1300 1400
  • 1.2GHzまでしか使わない
    • /system/etc/normalmode.shで
echo 1 > /sys/module/cpu_tegra/parameters/system_mode
echo 1200 > /sys/kernel/tegra_cap/core_cap_level

これが効いているらしく、ログに

V/NvPowerMgr(  416): setPowerState(): scaling, capLevel, capState, userCap, aggressiveness = 1, 1200, 1, 1200000, 29
    • turbomode.shを使うとスペック通りに、1コア時Max 1.4GHz、マルチコア時Max 1.3GHzで動作する
  • アプリケーションによるマルチコア利用
    • ホーム画面のスワイプは2コアを1.2GHzで回す高負荷処理
      • 思ったより重い処理なのでむやみにぶいんぶいんすると電池持ちに影響するかも
    • Grow Ballは4コア全開
    • Rip Tideは3コアしか使わない
      • 通常処理に2コア。水滴などのTegra 3追加効果の処理に1コア。
    • twiccaは更新時に3コアまで全力で使う
    • 他のアプリはほとんど2コアの全力で収まってしまう
    • コンカレントGCに別コアを起こすような挙動は見られない
  • 1.2GHz x 2 -> 760MHz x 2 -> 1.2GHz x 1 -> 600MHz x 1のような推移
    • 負荷に応じてコア数とクロックをうまく調整してくれている
  • sleepで寝ないv8
    • ブラウザでGoogle Newsを開いた状態でsleepすると204, 370, 620をうろうろする
    • すべてのアプリを閉じてホームに戻ってからsleepすると、102MHz
    • PC版Googleホームでも同様にsleepしてもCPUクロックが落ちない。v8が寝ない。
    • PC版Googleホームはsleepしなくても370, 620, 880, 1200をうろうろする
    • PC版iGoogle
    • Mobile版は102MHzに落ち着く。


どうもsleepしても、ブラウザがActive状態だとv8は寝ないようなので、sleepするときはブラウザを閉じてからの方が、電池持ちがよくなりそう。これは他のAndroid端末に共通なのかもしれない。

Android Security読書感想文

Android Security  安全なアプリケーションを作成するために

Android Security  安全なアプリケーションを作成するために

タオソフトウェアさん*1が執筆されて、インプレスさん*2から出版されている「Android Security」を、なぜか献本頂いた。ありがとうございました。


こんな人は是非読むべきだと思う。

  • Androidアプリケーションを受託開発している
  • Androidアプリケーションを外注しようとしている
  • Androidアプリケーションを開発しているが、セキュリティについては考えたこともない
  • 普通のAndroidユーザだが、パーミッションの意味をあまりよく分かっていない


開発者だけでなく、普通のAndroidユーザに薦めたいのは、P.117からの「6.5 疑われやすいパーミッションの組み合わせ」だ。立ち読みでもいいから一度目を通してもらいたい。あまりAndroidアプリが危険が危ないと煽るつもりはないが、どういう危険性があるかというのは認識しておくべきだと思う。


それにしても、READ_PHONE_STATEを要求するアプリ大杉だろ。