2011年05月

「いまどこ?」を公開します。

C2DMを使ったアプリです。特定の相手の端末の位置を照会します。7月末までをβテスト期間にしています。最初はいろいろと問題があると思いますが、興味のある方は是非お試し下さい。

 

この先数週間で99カ国を追加します

Google I/O 2011のAndroid Marketのセッションビデオで、「この先数週間で99カ国を追加します。合計で131カ国で購入できるようになります。」とありました。これはすごいです。これとは別に、ノルウエーのユーザーから、ノルウエークローネの価格が間違っていると指摘があり、訂正しようとして気付いたのですが、いつの間にか販売可能国が増えていました。これからポコポコ追加して131カ国まで増えるということでしょうか。これは実に素晴らしいです。Android Marketの販売可能国が少ないのはずっと問題視されてきていましたので。Googleはこれまでずっと「努力している」とは言っていましたが、なかなか増えませんでした。でも今回の発表できちんと投資をしてくれていたことが分かりました。

カレアラはこれまで配布可能地域を、デベロッパーコンソールで、「すべての国」にしないで、有料版を販売できる国だけを選択するようにしていましたが、もうめんどうなので「すべての国」にチェックを入れました。きっと一部の有料版を販売できない国で無料版を配布してしまうことになり、これは正しくは不適切ですが、実質管理できないので割り切ります。Android Marketのデベロッパーコンソールで、無料版の配布国を、有料版を販売できる国にする、という設定があるといいのですけどね。

 

米国での販売に必要なEINの取得

今日、米国からの郵便が届きました。EIN取りましたよ、というものでした。

Android Marketでアプリを販売する場合は求められないし、iPhoneのAppStoreも現在は不要になったと聞いていますが、Amazon AppStoreやMobiHandはEINを求めます。免税に必要な番号なのですが、このEINの取得ではハマる人も少なくないようです。で、数万円の手数料で申請を代行するという商売もあるようで、ググるとそっちの方がたくさんひっかかります。

さて、僕はAndroid Market以外でもアプリを販売できるようにしたいので、このEINは取得したいものの1つでした。こちらのサイトを参考にして書類に記入して4月17日にFAXしました。

FAXした後で電話もすると良い、という記述も見かけますが、見知らぬ人と英語で電話するのは大変なのでしませんでした。それでも4週間以内に届きました。良かった。

で、同じ悩みを持つ方のために僕が記入したSS-4書類をお見せします。個人情報は塗りつぶしています。

  • PDFに入力し、印刷してFAXしました。左下のSignatureは直筆で。その右側には記入日を APR 17, 2011 みたいに。

  • 4a, 4b は日本の住所を英語表記で書きます。4bの最後は、 Japan, 123-4567 です。最後の番号は正しい郵便番号にします。


EINを取得したい人の参考になれば幸いです。

 

Map用APIキーの自動選択

AndroidでGoogle Mapを使うのに必要なAPIキーは、デバッグ版とリリース版(リリース用に署名したもの)で異なりますが、これは開発者にとって共通の頭痛の種のようです。僕も困りました。まず、APIキーを指定する方法は2つあります。

  • レイアウトファイルに、android:apiKey= で記述する。

  • MapViewのコンストラクターで渡す。


MapViewをコードで生成する場合は、デバッグ版かリリース版かに応じて渡すキーを切り替えればいいので簡単です。が、MapViewを使う画面のレイアウトが複雑で、XMLで書いたレイアウトを使いたい場合は前者に目が行きます。僕もそうでした。で、こちらにある方法を試したのですが、どうしても、インフレートしたViewStubをMapViewとして使えません。かと言って、デバッグ版とリリース版で、apiKeyだけ違うXMLファイルを持つのはメンテナンス性が悪いので避けたいです。で、stackoverflowを見ていると、同じ悩みを持っている人への回答として、「MapViewをコードで生成してレイアウトに追加すれば良い」とありました。なるほど。

それで、そのMapVIewを使う画面のレイアウトはXMLで記述しますが、MapViewを入れるところは空のLinearLayoutにし、
    <LinearLayout
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

コードでMapViewを生成してaddViewしました。
        setContentView(R.layout.map);
ViewGroup layout = (ViewGroup)findViewById(R.id.mapview);
String mapKey;
if(BuildOption.isDebugBuild(context))
{
mapKey = mapKeyDebug;
}
else
{
mapKey = mapKeyRelease;
}
mapView = new MapView(context,mapKey);
mapView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
layout.addView(mapView);
mapView.setEnabled(true);
mapView.setClickable(true);
mapView.setBuiltInZoomControls(true);

この方法ではMapViewのコンストラクターにAPIキーを渡すので、.javaのコード中に文字列としてキーを持てば良く、レイアウトファイルに書く必要はありません。僕はこの方が好きです。で、デバッグ版かリリース版かの判定ですが、正しくは、デバッグ用の署名をしているか、リリース用の署名をしているかの判定をしたいところです。こちらには、AndroidManifest.xmlにあるandroid:debuggableの状態を使う例があります。ほとんどの場合はこれでもいいと思いますが、stackoverflowに署名を見て判断する方法があったので、それを使うことにしました。リンク先にある、「Had the same hassle with the API key. Here's a full solution, based on the above link and example from Bijarni (which somehow didn't work for me), I use now this method:」で始まる回答です。ちょいと分かりにくいですが、最初はDEBUG_SIGNATURE_HASHを0などにし、for文の中で sigs[i].hashCode() をログに出して、署名のハッシュを表示させます。署名せずに動かせば、デバッグ版の自動署名の値が手に入ります。それを、DEBUG_SIGNATURE_HASHに入れます。あと、そのコードには、

private static Boolean _isDebugBuild = null;

が抜けていますね。

SCREEN_ORIENTATION_REVERSE_LANDSCAPE

先日、こちらに端末の回転対応について書きましたが、そこにある方法では不十分なことが分かりました。Galaxy SとXPERIA ARCは逆さの横持ちに対応しています。横持ちは通常端末を反時計回りに回転させますが、その反対でも横向き画面になります。僕が持っているos2.1の端末は、この状態に対応していません。どうやら、os2.2以降だと逆さの縦持ちもアリのようですが、上記端末ではこれはサポートしていないようです。で、Galaxy S(まだ2.2.1を我慢しながら開発に使用中)とXPERIA ARCでは、逆さ横持ちの状態で画面の回転に応答しないようにすると、こちらで触れたコードでは(当然ですが)画面が逆になってしまいます。SCREEN_ORIENTATION_REVERSE_LANDSCAPEにしないといけないからです。で、次のコードにしました。(逆さの横持ち、縦持ちの定義はos2.3以降にしかないので、それより前の端末ではその状態をサポートしているものがあったら、Webによるとあるようですが、下記のコードでは対応できません。Galaxy Sもそうです。)
    public static void setFixedOrientation(Activity activity,Context context,boolean fixed)
{
if(fixed)
{
Configuration config = context.getResources().getConfiguration();
int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; // warning回避
Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
boolean use_reverse_mode = false;
if(Build.VERSION.SDK_INT >= 9 && (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270))
{
use_reverse_mode = true;
}
if(config.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
if(use_reverse_mode)
{
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
else
{
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}

}
else if(config.orientation == Configuration.ORIENTATION_PORTRAIT)
{
if(use_reverse_mode)
{
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}
else
{
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
}
activity.setRequestedOrientation(orientation);
}
else
{
//this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}

それから、端末の回転対応についてはこちらも必見です。