2012年3月17日土曜日

[Android] エコ技・技ありモードについて

先日、Sharp Androidアプリ開発テクニカルセッションに参加させていただきました。
シャープ製2012年秋冬モデルの端末はエコ技・技ありモードというバッテリーの消耗を軽減する機能が追加されました。
端末の画面が消灯中なら「技ありモード」はアプリケーションの特定の動作を一時的に止めます。sendBroadCastを無効にします)
アプリケーションを一時停止させることで、バッテリーが最大2.5倍長持ちするとのことです。

その副作用として正常なアプリケーションが動かなくなる可能性があります。
バックグラウンドでBroadCastを送信・受信するアプリケーションは確実に影響を受けます
2012年3月時点で「技ありモード」を搭載する端末は次の通りです。
docomo SH-01D
SH-02D
SH-04D
SH-06D
Softbank 101SH
102SH
103SH
104SH
DM011SH
DM012SH
au IS13SH
IS14SH
INFOBAR C10
EMOBILE A01SH
WiMAXモデル EB-A71GJ

画面消灯中の動作が必要なアプリケーションは「省エネ待受対象外リスト」に設定することで動作するようになるとのことです。
セキュリティ保護のためのアプリケーションは省エネ待受対象外リストに設定するべきだと思います。

最近、QuickPicというアプリケーションが日本のPlayストア(旧Androidマーケット)での公開を停止するということがありました。
理由は日本だけ「ファイルが消えた」というクレームがが多いとの理由でした。
日本で販売されているAndroid端末はそれぞれに個性的な独自仕様が盛り込まれているため、クレームの原因は独自仕様によるものではないかと思います。

「技ありモード」はユーザーの不満の一つであるバッテリーの持ち時間を改善するすばらしい機能です。
しかし、Ansroid-SDKの仕様を逸脱した機能でもあります。
将来「技ありモード」がどう影響するか不明ですが、QuickPicのように日本のユーザーによるクレームが炎上する可能性は十分にあり得ます。

以上、参考になれば幸いです。

2012年3月10日土曜日

[Android] Toastに画像やボタンを表示するには

How to draw images or buttons on Toast

ToastにはViewを表示する機能があります。
Android-SDKに添付されているアイコンの画像(ic_launcher.png)を表示するサンプルを作ってみました。

Activity(Main.java)

Toastで表示した文字や画像は一定時間後に自動で消えます。
自分で「一定時間後に消す」という処理を書くと複雑なプログラムになりがちです。
Toastを使えば表示した文字や画像が一定時間後に自動で消えます。アクセス許可が無くても使えるのでとても重宝します。

ちなみにViewなら何でも表示できるようです。
たとえばボタンの表示も可能です。

ただしToastでボタンを表示してあまり意味がありません。すぐに消えてしまうのでクリックする暇がありません。

関連ブログ
[Android] Toastをcancelするには
[Android] SurfaceviewにToastを表示するには

以上、参考になれば幸いです。

2012年3月3日土曜日

[Android] セキュリティ対策

how to maintain Android security

最近、政府のサーバーがサイバー攻撃を受けたと何度も報道されてます。
PCがコンピューターウィルスに感染しパスワードが流出したケースもあるようです。

Androidスマートフォンの利用者も他人事ではありません。
Androidがサイバー攻撃されると次のようなことが考えられます。
  • 端末に保存されているファイル(電話帳、メール、カメラで撮影した動画など)が流出したり、消されたりする
  • 端末が乗っ取られてサイバー攻撃に利用される
こんなことは簡単に起こりませんが、絶対無いとは言い切れないので用心が必要です。
Android Marketは「Bouncer」によりマルウェアを排除していますし、ウィルス対策アプリをインストールする方法もあります。
しかしそれだけでは万能とはいえません。
自分でできるサイバー攻撃対策をいくつか考えてみました。
  • Android Market以外で配布されているアプリケーションはインストールしない
  • アプリケーションのインストール前に「アクセス許可」を見て安全性を判断する
  • 定期的にバックアップする

「アクセス許可」とは何か
Androidアプリケーションは必ずマニフェストを持っていて、そこに特定の動作をするために必要なアクセス許可が書かれています。
Android Marketにはすべてのアプリケーションごとにアクセス許可が掲載されていて、ユーザーはインストールする前に確認することができます。

どんな「アクセス許可」が危険なのか
結論を言うとアクセス許可だけで危険性を判断できません
アクセス許可がなければアプリケーションでできることは限られてしまいます。
ただし、アクセス許可の組み合わせによってはユーザーの意図しない動作ができてしまいます。

【完全なインターネット アクセス】
ホームページの表示、動画のダウンロード、掲示板への書き込みなどに必要なアクセス許可です。

【端末のステータスと ID の読み取り】
このアクセス許可は「端末の電話番号やシリアル番号、通話中かどうか、通話相手の電話番号」を抜き取ることができます。
「完全なインターネット アクセス」と同時に許可すると端末や通話相手の電話番号をインターネットのサーバーに送信することができてしまいます。

【連絡先データの読み取り】
アドレス帳などの読み取りに必要なアクセス許可です。
「完全なインターネット アクセス」と同時に許可すると連作先データをインターネットのサーバーに送信することができてしまいます。

【USB ストレージのコンテンツの変更/削除、SD カードのコンテンツの変更/削除】
SDカードに保存した音楽や動画のファイルの読み書きや削除したり、隠したりできます。
「完全なインターネット アクセス」と同時に許可するとファイルをインターネットに送信することができてしまいます。

この画像はAndroid Marketで公開されている無料ゲームのアクセス許可です。
Mtkはこのゲームが好きなのですが、ゲームのアクセス許可としてはあまりにも過剰だと思いました。
たとえば「ゲームのスコアランキングをインターネットで競える」という機能があるならIDの読取りとインターネットアクセスは必要です。
しかしそのような説明はありません。
このアプリが悪い見本というわけではありません。ユーザーレビューでは高く評価されています。
自分の端末をどう使うかは自己責任です。よく考えた結果、ダウンロードを断念しました。

アクセス許可が少ないアプリケーションが他のアクセス許可を持つアプリケーションと連係してサイバー攻撃することもあり得ます。

以上、参考になれば幸いです。

2012年2月25日土曜日

[Cubase] Mystic・Prologue・Spectorの同時発音数の設定方法

How to make Mystic, Prologue, Spector change the number of voices

Cubaseにはシンセサイザーがたくさん付属しています。
なぜかMystic・Prologue・Spectorの3つは同時発音数の設定方法がマニュアルに書いてありません。
初期設定ではモノフォニック(単音)しか鳴らせません。

設定箇所は画面右上(max voices)、コンソールの外側です。
ちなみに画面左上(pitchbend range)でピッチベンド幅が設定できます。2で1音階、12で1オクターブです。

左上がピッチベンド幅、右上が同時発音数
いじっているうちに偶然気がつきました。

同時発音数を2以上に設定した場合はポルタメント効果はなくなります。(このことはマニュアルに書いてあります)

この3つのシンセは音色が個性的なので効果音を作るのに重宝します。
ただしパラメーターが多くて初期状態から音色を作るのは難しいのでプリセットを少し加工して使ってます。
音色をねらって作るのは難しいです。

もうすぐSteinbergからPadshopというシンセサイザーが発売される聞いてふと思い出しました。
http://japan.steinberg.net/jp/products/vst/padshop/start.html
Padshopも難しそうですが音作りの幅は広そうです。

以上、参考になれば幸いです。

2012年2月18日土曜日

[Android] BitmapクラスのOutOfMemoryErrorを防ぐ #2

How to correct the OutOfMemoryError of Bitmap class #2
前回は画像表示のたびにBitmapFactory.decodeResourceを実行して、表示後にrecycle()メソッドで解放する方法でOutOfMemoryErrorを防ぎました。
この方法は安定して動作しますが、表示のたびにファイルにアクセスしてデコード処理を実行するので効率が悪いような気がします。

そこで他の方法を考えました。
Bitmapクラスは画像を整数の配列に変換する getPixelsメソッド と、整数の配列を画像に戻す setPixelsメソッド があります
画像を配列に変換したり、配列を画像に変換する処理はCPUとメモリー(RAM)の間のデータ転送が主な内容になるはずです。
ファイルアクセスやデコード処理が1回で済むのでもっと効率が上がりそうです。

今回は1024×1024ピクセルの4枚の画像を整数の配列に変換することをを試してみます。
成功すればBitmapFactory.decodeResourceは各画像につき1度しか実行されないので効率が上がるはずです。

Main3
結果
整数の配列の確保(new int[1024 * 1024])でOutOfMemoryErrorが起きてしまいました。
Android1.6と2.1のエミュレーターで確認しました。
Androidのint型は4バイトなのでint[1024 * 1024]の配列は連続した4MBの空きメモリー(RAM)が必要になるわけですが、それを4つも確保するのは難しいようです。
int[1024][1024]の2次元配列を使う方法に直して試みましたがやっぱりOutOfMemoryErrorが起きました。

RAM容量の多い端末で正常動作するかもしれませんが、エミュレーターで動作しない方法なのでお勧めできません。

ちなみにgetPixelsメソッドはJNI(Android-NDK)のOpenGLでポリゴンのテクスチャを貼り付けるときに必須のメソッドです。
http://blog.fujiu.jp/2011/08/android-android-ndk.html

今回はわざと大きい画像や配列を扱ってエラーが出ることを確認しました。
将来のAndroid端末は今以上にRAMの大容量化、画面の高解像度化が予測されます。
Android-SDKやOSも進化して大きいBitmapを扱いやすくなってます。
古い端末でも簡単に扱えるようになったらいいですね。


以上、参考になれば幸いです。

2012年2月11日土曜日

[Android] BitmapクラスのOutOfMemoryErrorを防ぐ

How to correct the OutOfMemoryError of Bitmap class

Android端末は種類が多く、画面解像度も機種ごとに違うので画像の扱いは大きな悩みどころです。
たとえばSurfaceViewに画像を表示する場合、大きめの画像データ(1024×1024ピクセル)を用意して画面解像度に合わせて縮小表示する方法が一番簡単のように思います。
ところが、Androidは大きい画像を下手に扱うと BitmapFactoryクラスが OutOfMemoryError が発生することがよくあります。

すでに多くの開発者がOutOfMemoryErrorを回避する方法を公開しています。
今更ながらMtkもいくつか方法を考えてみました。

4枚の1024×1024ピクセルの画像を1秒ごとに表示するアプリケーションで説明します。
画像は画面解像度に収まるように拡大縮小表示します。

1024×1024ピクセルのこんな画像を4種類用意します。
それぞれのファイル名はimage1.png、image2.png、image3.png、image4.pngとしました。
Androidのプロジェクトのresフォルダーの下にdrawableフォルダーを作成し、この4つの画像を保存します。

OutOfMemoryErrorが出るサンプルです。Android1.6のエミュレーターで確認しています。
※Android2.1のエミュレーターでは正常に動作しましたが実機ではOutOfMemoryErrorが起こり不安定です。
Main.java(Activity)
※Android1.6以上、パーミッション不要のため、マニフェストは省略します
Android1.6エミュレーターでアプリを実行すると
bmp2 = BitmapFactory.decodeResource ・・・
でOutOfMemoryErrorが発生します。
1024×1024ピクセルの画像(Bitmapのインスタンス)をメモリー(RAM)に置くことができないようです。

次はOutOfMemoryErrorが起きないように修正したサンプルです。
Main2.java(Activity)
Bitmapの表示のたびにファイルからロードし、次のbitmapファイルを開く前にrecycle()メソッドを実行します
表示するたびにファイルにアクセスするのは効率が悪いような気がしますが、Bitmapをメモリー(RAM)に置いておけないのだから仕方ありません。

今回はSurfaceViewを使いました。
GLSurfaceViewでポリゴンにテクスチャを貼り付けるときも GLUtils.texImage2D の直前でBitmapをロードし直後にrecycle()すると安定する思います

次回は他の方法を試してみる予定です。
公開しました http://blog.fujiu.jp/2012/02/android-bitmapoutofmemoryerror-2.html


以上、参考になれば幸いです。

2012年2月4日土曜日

[Java] thisとは #2

What is "this" #2

AndroidアプリケーションのJavaソースにthisを使うことがよくあります。
たとえばToastです。

Main.java(Activity)

ToastクラスのmakeTextメソッドにthisを渡しています。
thisはインスタンス化されたクラス自信です。
このソースはMainクラスの中のthisなので、インスタンス化されたMainクラス自身ということになります。

・なぜmakeTextメソッドにthisを書くのか?
Toastクラスのリファレンスを見てみます。
http://developer.android.com/intl/ja/reference/android/widget/Toast.html
makeTextメソッドの説明にはこう書かれてます。
makeText(Context context, CharSequence text, int duration)
Android-SDKをインストールしたeclipseならマウスをメソッドにホバーするとリファレンスが表示されます。

1壱番目の引数はContextを渡すことになってます。

上のサンプルでmakeTextメソッドに渡したのはContextクラスではなくMainクラスのthisです。
正常に動くけど渡すべきクラスが違うように見えます。

・なぜMainクラスのthisで動くのか?
上のサンプルのMainクラスは次のように定義しています。
public class Main extends Activity
MainクラスはActivityクラスを継承しています。
はActivityクラスのリファレンスを見てみます。
http://developer.android.com/intl/ja/reference/android/app/Activity.html
ここにはこんなことが書かれてます。

java.lang.Object
android.content.Context
android.content.ContextWrapper
android.view.ContextThemeWrapper
android.app.Activity
Activityがどのクラスを継承しているかを説明しています。

ActivityクラスはContextThemeWrapperクラスを継承したサブクラスで
ContextThemeWrapperクラスはContextWrapperクラスを継承したサブクラスで
ContextWrapperクラスはContextクラスを継承したサブクラスです。

つまりMainクラスはContextクラスを継承しているのでContextクラスとして振る舞うことができるのです。
makeTextメソッドに渡したthisはContextクラスを継承したMainクラスだからToastが正常に表示されたわけです。
ServiceクラスもContextクラスを継承しています。
http://developer.android.com/intl/ja/reference/android/app/Service.html
ServiceクラスもでToastを表示するときもmakeTextメソッドにthisを渡します。

・Contextのサブクラス以外のthis
Android-SDKのApiDemosのRotationVectorDemo.javaにこんなコードがあります。

mSensorManager.registerListener(this, mRotationVectorSensor, 10000);

registerListenerメソッドの第1引数はSensorEventListenerインターフェイスを渡すことになってます。
このMyRendererクラスの定義です。
class MyRenderer implements GLSurfaceView.Renderer, SensorEventListener
MyRenderer クラスはSensorEventListenerインターフェイスを継承しています。
SensorEventListenerインターフェイスを継承したクラスのthisはSensorEventListenerとして振る舞うのでregisterListenerメソッドに渡せば動作するわけです。

前回の [Java] thisとは で書ききれなかったAndroidアプリケーションのソースのthisについての説明でした。

以上、参考になれば幸いです。