Android サイリウムアプリ公開
久々に、Androidアプリを公開しました
今回も前回と同じように3日で完成
個人的に時間をかけてアプリを作るよりは、さっさと形にして叩きながら機能改善していく方が好きです
カラフル サイリウム
https://market.android.com/details?id=com.ColorfulCyalume
今回のアプリで工夫したところは
・アプリ起動中はスリープに入らないようにする
・画面輝度を最大にする
・メニューアイコンを動的に変化させる
・加速度センサーを使う・ローパス・ハイパスフィルターを使う
仕事ではC++ばっかりなので、久々のJavaでした。
オブジェクト指向がだんだん分かってきたので、コードの書き方も前よりはスマートになったかな
次は何を作ろうかなぁ
あと、Androidの勉強会はどこかのタイミングで出席したい
WebKit GTK版をビルドする
ほとんど↓通り
http://96inu.blogspot.com/2009/09/debiangtkwebkit.html
Subversionのインストールをして
$ sudo apt-get install subversion
ソースをチェックアウト
$ svn co http://svn.webkit.org/repository/webkit/trunk
設定をしてからビルドをする
$ cd trunk
$ WebKitTools/Scripts/update-webkit
$ WebKitTools/Scripts/set-webkit-configuration --release
$ WebKitTools/Scripts/build-webkit --gtk
いろいろとエラーが出てくるので、そのたびに必要なパッケージをインストールする
特にうまく行かなかったのは以下の2点
GLIBではまったときはPATHに/usr/include/glib-2.0を設定したらうまくいった
$ export PATH=$PATH:/usr/include/glib-2.0
libsoupもなかなかうまくいかず、libsoup-2.33.6をダウンロードしてきて(http://ftp.acc.umu.se/pub/gnome/sources/libsoup/2.33/)
$ tar zxvf libsoup-2.33.6.tar.gz
$ cd libsoup-2.33.6
$ ./configure
$ make
$ sudo make install
でうまくいった
設定画うまく行けばビルドが始まる
1時間ほどでビルドができた
===========================================================
WebKit is now built (1h:02m:52s).
To run GtkLauncher with this newly-built code, use the
"Tools/Scripts/run-launcher" script.
===========================================================
実行は以下のコマンド
$ WebKitBuild/Release/Programs/GtkLancher
Windowが立ち上がりブラウザ画面が開く
Acid3は99点なのね
Sunspider 0.9の結果
WebKit Firefox 3.6.12
432.8ms +/- 4.4% 1035.2ms +/- 2.1%
土日に移植層が作れるかどうか検討してみよう
Androidアプリ2本 マーケットで公開中
先週くらいからAndroidマーケットでアプリを2本公開しています
ガイガーカウンター
http://market.android.com/details?id=com.XmlTest
水の安全
http://market.android.com/details?id=jp.tkada.gaigerwater
今回のアプリ公開で、Androidマーケットの署名やバージョン管理方法なども勉強できました
公開したあとってパッケージ名に変えられないんですね・・・
それにより、ガイガーカウンターの方は「com.XmlTest」なんて名前に…
これらのアプリに関してはこまめにアップデートを行う予定です
アンドロイダーでの紹介記事
http://androider.jp/a/e62d11728cc7c99c/
http://androider.jp/a/c4293b738cc5699d/
Exドロイドでの紹介記事
http://exdroid.jp/d/3626/
アンドロイドスーパーでの紹介記事
http://arar.tk/archives/219
Android ColorPickerDialogの使い方
お絵かきアプリを作る際に色選択は必須
カラーパレットを用意してやって・・・ってのもいいけど
Android SDKのサンプルに良いものがあるので流用してみる
1.samples\android-7\ApiDemos\src\com\example\android\apis\graphicsの中にある
ColorPickerDialog.javaをプロジェクトに組み込む
2.Dialogとして呼び出す
package com.example.android.apis.graphics; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; public class ColorSelect extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ColorPickerDialog cpd=new ColorPickerDialog(this, new ColorPickerDialog.OnColorChangedListener() { @Override public void colorChanged(int color) { // 色が選択されるとcolorに値が入る int R=Color.red(color); int G=Color.green(color); int B=Color.blue(color); android.util.Log.d("ColorPickerDialog", "(R,G,B)=("+R+","+G+","+B+")"); } },Color.BLACK); cpd.show(); } }
参考:http://y-anz-m.blogspot.com/2010/05/androidcolorpickerdialog.html
シンプルなAndroidカメラアプリ
参考:http://androidlab.blog119.fc2.com/blog-entry-21.html
package com.tkado.SimpleCamera; import android.app.Activity; import android.content.Context; import android.hardware.Camera; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.Window; import java.io.*; import java.util.Calendar; // ---------------------------------------------------------------------- public class Camera_test extends Activity { private Preview mPreview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Hide the window title. requestWindowFeature(Window.FEATURE_NO_TITLE); // Create our Preview view and set it as the content of our activity. mPreview = new Preview(this); setContentView(mPreview); } } // ---------------------------------------------------------------------- class Preview extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder mHolder; Camera mCamera; String SD="/sdcard/DCIM/102SC/"; //SDカードの保存先フォルダ Preview(Context context) { super(context); // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, acquire the camera and tell it where // to draw. mCamera = Camera.open(); try { mCamera.setPreviewDisplay(holder); } catch (IOException exception) { mCamera.release(); mCamera = null; } } public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return, so stop the preview. // Because the CameraDevice object is not a shared resource, it's very // important to release it when the activity is paused. mCamera.stopPreview(); mCamera.release(); mCamera = null; } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(w, h); parameters.setPictureSize(w*2, h*2); //プレビューサイズの2倍の大きさで画像を保存する mCamera.setParameters(parameters); mCamera.startPreview(); } public boolean onTouchEvent(MotionEvent e){ if(e.getAction()==MotionEvent.ACTION_DOWN){ Log.d("TEST","X:"+e.getX()); Log.d("TEST","Y:"+e.getY()); } takePicture(); return false; } //写真撮影 public void takePicture() { //カメラのスクリーンショットの取得 mCamera.takePicture(null,null,new Camera.PictureCallback() { public void onPictureTaken(byte[] data,Camera camera) { try { mCamera.stopPreview(); Log.d("Camera","Take picture"); File dirs = new File(SD); if (!dirs.exists()) { dirs.mkdirs(); //make folders } String outputfile=Calendar.getInstance().getTimeInMillis()+".jpg"; //ファイル名が被らないように時間で名前を付ける String filename=SD+outputfile; Log.d("Camera", "output:"+filename); FileOutputStream fos = null; try { fos = new FileOutputStream(filename); fos.write(data); } catch (IOException e) { e.printStackTrace(); mCamera.stopPreview(); mCamera.release(); android.util.Log.e("",""+e.toString()); } finally { fos.close(); Log.d("Camera", "Done:"+filename); } mCamera.startPreview(); } catch (Exception e) { mCamera.stopPreview(); mCamera.release(); android.util.Log.e("",""+e.toString()); } } }); } }
あとはカメラを使うためにAndroidManifest.xmlに
を追加する。
そしてAndroid2.1以下ではカメラが横向き専用のため
と横向き固定にしておく。
カメラで撮って保存するだけなら非常に簡単なのだが
撮ったあとに確認画面を表示したり
プレビュー中の画像に画像処理を加えるのは一癖も二癖もあるみたいで苦戦中
IS03開発用ドライバ
IS03買ってきたのでさっそく自作アプリを動かす
1.ドライバのダウンロード
http://k-tai.sharp.co.jp/support/a/is03/download/usb/index.html
https://sh-dev.sharp.co.jp/android/modules/driver/index.php?/is03_adb/download
2.ドライバのインストール
3.IS03を接続
4.adb devicesでデバイスが見つかればOK
と、流れは簡単なのだが何度やってもうまく行かず
インストール・アンインストールを2回くらい繰り返して
ようやくadb devicesで見つかるようになった
しかし、高速転送モードが使えなくなってしまった
う〜んよくわからん。
直り次第ここに追記しよう
adb devicesで見つかればあとはEclipseから実行してあげれば
自動的にインストールと実行がされる
BitmapのOutOfMemoryErrorと戦った
画像処理はできるようになったので次はSDから画像を読み込んで画像処理をしたいなと思って挑戦
AndroidにはGalleryってのがあって端末に含まれている画像を収集して一覧として表示してくれる機能がある
そこからインテントを受け取ればどの画像が選択されたか簡単に分かるはずなのだが・・・
※Galleryについてはこちら
http://www.conit.co.jp/labs/index.php?e=255
package com.tkado.sdtest; import java.io.*; /*省略*/ public class SD_test extends Activity { final int REQUEST_PICK_CONTACT=99; Bitmap mBitmap; ImageView image; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); image=(ImageView)findViewById(R.id.ImageView01); String inputname="/sdcard/test2.txt"; try{ byte[] buf = new byte[ (int) new File( inputname ).length() ]; BufferedInputStream f = new BufferedInputStream( new FileInputStream( inputname ) ); f.read( buf ); f.close(); TextView txt=(TextView)findViewById(R.id.TextView01); String s=new String(buf, "SJIS"); txt.setText(s); } catch( IOException e){ TextView txt=(TextView)findViewById(R.id.TextView01); txt.setText("ERROR:"+inputname); } Button button1=(Button)findViewById(R.id.Button01); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO 自動生成されたメソッド・スタブ // インテント設定 Intent intent = new Intent(Intent.ACTION_PICK); // とりあえずストレージ内の全イメージ画像を対象 intent.setType("image/*"); // ギャラリー表示 startActivityForResult(intent, REQUEST_PICK_CONTACT); } }); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); Log.d("tag","onActivity"); if(requestCode == REQUEST_PICK_CONTACT){ //Content Providerとは、全てのアプリケーションからデータの読み書きが可能なオブジェクトで、パッケージ間でデータ共有を行う唯一の手段 Log.d("tag","inif"); Uri photoUri = data.getData(); ContentResolver cont_reslv = getContentResolver(); if (photoUri != null) { try { if(mBitmap!=null){ mBitmap.recycle(); mBitmap=null; } mBitmap = MediaStore.Images.Media.getBitmap(cont_reslv, photoUri); image.setImageBitmap(mBitmap); } catch (Exception e) { e.printStackTrace(); } } } } }
このコードのキモはここ
if(mBitmap!=null){ mBitmap.recycle(); mBitmap=null; }
これがないとOutOfMemoryErrorが出てきてどうしようもなかった
ここらへんがかなり参考になった
http://groups.google.com/group/android-group-japan/browse_thread/thread/fa40fe4d250541f5
http://mtnk.org/down/PDF/OutOfMemoryError.pdf
なんとか画像の切り替えができるようになったので
次は画像処理をしてSDへの保存、カメラアプリとの連動、メールアプリとの連動辺りをやりたいな
実はOutOfMemoryErrorもネイティブコードを使えば簡単に回避できるらしいね