2014年2月26日水曜日

Android4.3 で暗号化処理が変わる・・・?

自力では調査しきれなくて先輩に助けて頂いた内容だけど、今後のためにメモ。


つい先日(2014/2/17)にGalaxyS4のOS4.3アップデートが開始されまして、
「(暗号化して保存している)IDが表示されない(復号化できない)よ!!」
とたくさん報告があがってくるようになりました。

何度も寄り道しながらやっと突き止めた原因はなんと、
4.2から4.3で暗号化に使うプロバイダのデフォルト値が変わっている
というものでした。
OS4.2より前のデフォルトは(ほとんどが)Bouncy Castle ですが、
OS4.3、4.3はAndroidOpenSSLに変わっています。


具体的に何が起こったのかというと、
4.2より前の端末で暗号化 (Bouncy Castle) したものを、
4.3(AndroidOpenSSL) で復号しようとしているので、エラーになるというものでした。

対策としては、暗号化と復号化のプロバイダをちゃんと指定してやれば
デフォルト値を使われることがないので、とりあえず復号化できるようになります。



Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
このように書いてしまうと、デフォルトプロバイダが適応される
               ↓
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
このように書いてやれば、BC(Bouncy Catsle)を指定できる

AndroidOpenSSLを指定する場合はこう。
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "AndroidOpenSSL");



とりあえずこれで解決なのですが、今までのOSに採用されていた
Bouncy Castleのバージョンを調べてみると、ちょいちょい更新されているみたいなんです。
で、今回のいきなりのデフォルト値変更。
今後またデフォルト値が変わったり、BCがなくなったりする可能性がゼロではないことを考えると、
暗号化ライブラリを自分で用意してやるのが一番安全だろう、という結論になりました。



で。
すでにデフォルト値で暗号化・保存したIDを利用するアプリをリリースしちゃっているので、
次バージョンから内部でBCライブラリ持って復号化しよう!
と思ったんですが、Androidで採用されていたBCはどうやらカスタマイズされたものらしいんです。
おそらくそういう理由で、Android内部処理のBCで暗号化したものを、
拾ってきたBCライブラリで復号してやることはできませんでした・・・。


うーん、、なんだか。。。

2014年2月18日火曜日

Androidで画像をタイル状に敷き詰める

Androidアプリで画像をタイル状に敷き詰める方法。
xmlで指定する方法はたくさん見つかるのに、Javaから画像を指定する方法が少ないのでメモ。

Bitmapの画像データを設定してます。

※残念なことに、2.3系の端末だと縦に繰り返しができなかった

xml
<ImageView
        android:id="@+id/bg_image"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitXY" />
java
BitmapDrawable bd = new BitmapDrawable(bitmap);    // bitmap に指定したい画像
bd.setTileModeX(Shader.TileMode.REPEAT);
bd.setTileModeY(Shader.TileMode.REPEAT);
((ImageView)findViewById(R.id.bg_image))..setImageDrawable(bd);

Shader.TileMode は REPEATとMIRRORとCLAMPが選べる。




応用編

またまた残念なことに、超高解像度端末に対応する画像を用意してもらえなかったので、
画面サイズいっぱいに引き延ばして縦に繰り返して表示することになった実装が以下。

        // 縦横比を保ったまま横幅いっぱいにリサイズ
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        float widthScale = (float) metrics.widthPixels / result.getWidth();

        Matrix matrix = new Matrix();
        matrix.postScale(widthScale, widthScale);
        BitmapDrawable repeateImage
            = new BitmapDrawable(Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true));

        // 縦方向に繰り返し表示
        repeateImage.setTileModeY(Shader.TileMode.REPEAT);
        image.setImageDrawable(repeateImage);




2013年10月2日水曜日

support-v7-appcompatを使ってAndroid2系でActionBarを動かす

API level 18 から support-v7-appcompat を使って
古いOSでも ActionBar が使えるようになったと聞いたので、
さっそくやってみたら、エラー、エラー、エラー。
かなり苦労したので、記録に残します。

jar ファイルだけ libs に入れて関連付けてやればいいのかと思ったら、そうでもなかった。
jar ファイルだけだとリソースがないので、プロジェクトで追加しないとダメらしい。


※SDKはアップデートしておきます
※SDKマネージャーもアップデートが必要な場合、
 ライブラリの紐付け方とかいろいろ変わるので、
 既存のプロジェクトがある場合はいろいろ時間と覚悟が必要です


手順

http://developer.android.com/tools/support-library/setup.html#libs-with-res
↑のサイトを参考に support-v7-appcompat プロジェクトを作る。
Eclipseの場合を要約すると、

  1. SDK Manager を使って Android Support library をダウンロードする
  2. 新しいプロジェクトとして support-v7-appcompa をインポートする
    1. File -> Import を選択
    2. Existing Android Code Into Workspace を選択
    3. <sdk>/extras/android/support/v7/appcompat/ を選択
    4. Finish を押してインポートする ←わたしは念のためワークスペースにコピーしました。
    5. 作成した support-v7-appcompa プロジェクトの libs 内の android-support-v4.jar と android-support-v7-appcompat.jar を右クリックし、Build Path -> Add to Build Path を選択 ←このメニューが出てこない場合は追加済みなのでやらなくてよさそう
    6. プロジェクトを右クリックし、Build Path -> Configure Build Path を選択
    7. Order and Export タブで、今追加した v4 と v7 にチェックを入れる
    8. Android Dependencies のチェックは外す
    9. OKを押して、完了!
次に、自分で作りたいアプリのプロジェクトに v7 を設定する。

  1. 自分のアプリのプロジェクトを右クリックし、Properties を選択
  2. Android -> Library の Add をクリック
  3. さっき作った support-v7-appcompat を選択し、OKを押す
  4. 設定画面をOKで閉じる
と、ドキュメントに書いてある手順はここまで。
このあとビルドしたら、エラーになりました。

Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

どうやら、AndroidManifest に書いてあるテーマの変更が必要なようです。

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat" >
        <activity
             ・・・>
        </activity>
</application>

もう1つ、v4 がかぶってるよ的なエラーがでたので、自分のアプリのプロジェクトから
android-support-v4.jar を削除した。

これでビルドしてみたら、うまくいった!!!

2013年8月26日月曜日

Android 超高解像度端末一覧。(2013.8.26現在)

2013年8月26日現在の、解像度1080x1920のいわゆる「超高解像度端末」の一覧。

xxhdpiに分類されるこのとてもキレイな画面でアプリを開くと、
「画像が小さくなりすぎて見えない!!」「なんか表示がおかしい!ボタンがない!!」
みたいな現象がよく起こります。

大きめの画像を用意してやれば解決する話なんだとは思うけど、
まだ試せてないので解決策がまとまったらまた追加で記事に残します。


これからどんどん増えてくると思うので、無視してはいられない。


■docomo
ELUGA X P-02E Android4.1
ELUGA P P-03E Android4.2
ARROWS X F-02E Android4.1
ARROWS NX F-06E Android4.2
AQUOS PHONE ZETA SH-06E Android4.2
GALAXY S4 SC-04E Android4.2
Optimus G pro L-04E Android4.1

Xperia Z SO-02E Android4.1

AQUOS PAD SH-08E  (1200×1920 タブレット)

■au
HTC J butterfly HTL21 Android4.1

HTC J One HTL22 Android4.1
Xperia UL SOL22 Android4.1


■SoftBank
AQUOS PHONE Xx 206SH Android4.2
ARROWS A 202F Android4.2


■その他

新型Nexus 7  (1200×1920 タブレット)

2013年6月26日水曜日

Android アプリのハッシュキーの確認方法

■Windowsの場合
コマンドプロンプトで

keytool -exportcert -alias xxx -keystore /keystoreまでのパス/xxx.keystore | openssl sha1 -binary | openssl base64

を実行。

キーストアのパスワードを聞かれるので、用意しておくこと。

2013年5月24日金曜日

Google Maps V2 API でNoClassDefFoundErrorが出た。

java.lang.NoClassDefFoundError: com.google.android.gms.R$string
at com.google.android.gms.common.GooglePlayServicesUtil.c(Unknown Source)
at com.google.android.gms.internal.e.a(Unknown Source)
at com.google.android.gms.internal.e.onCreateView(Unknown Source)
...


Androidでこのエラーが出ていた場合、「Google Play開発者サービス」アプリがアンインストールされている可能性が考えられます。

このアプリはgoogleが勝手にインストールするアプリで、アンインストールしてもしてもしても一定時間で生き返ります。
現在発売されている端末には最初からインストールされているのですが、2012年10月頃以前の端末には説明が不十分なままアップデートで追加され、しかも容量が大きかったためにユーザーから大批判を買い、アンインストールするユーザーが続出しているようです。

もちろん、一定時間が経てばまたインストールされるのですが、Androidユーザーは「とにかく不必要なアプリは消したい」という思いが強いので、こまめにチェックしてはアンインストールしているようです。
今まで目立った不具合がなかったようなのですが、今回Google Map V2が使えないことが分かりました。

さらにこのアプリ、Google Play Storeから検索してもヒットしないんですね。
Google検索にはヒットするのでそこから入れなおすか、自動更新されるのを待つしかないので、ダウンロードの導線を付けてあげたほうが良いです。
(ちなみにfoursquareは、このアプリが入っていないとアラートを表示してダウンロードを促しています。)

今回はGoogle Maps V2 APIを利用しているところでこのエラーが発生しましたが、
今後GooglePlayServicesUtil.cを参照するプログラムで問題になってくると思います。

2013年5月22日水曜日

phpと外部js間で値を渡そうとして詰まったお話・・

phpでhtmlサイトを作っているとき、ふとphpの値をjsでも使いたいな・・・と思った。
jsは外部ファイルから読み込んでいる。

ぐぐってみた結果、php→javascriptの値渡しは簡単にできそうなことが分かった。

$a = 100;

<script type="text/javascript">
  var a = <?php echo $a; ?>;
</script>

しかし、全く動かない。
ていうか、値取れてないし!!




調べた結果、これには【 同じソース内に書かれているという大前提】があった。
つまり、外部javascriptを読み込んでいる場合はダメ。


よく考えてみたら確かに、phpでhtmlを出力してる時点でhtmlなわけなんだけど、
ぐぐって出てきたら「そんなことできるの!?」って思っちゃうじゃないですか。


こんな大前提なこと、書いてるサイトもひっかからないし・・・。
ということで、メモ。