2012年4月26日木曜日

[Android]スライドショーをつくってみる

長らくblogを更新しておりませんでした・・・。
こんにちは、@mogakanaです。とりあえず生きてます。

本日はスライドショー的なものをつくってみました。
SDカード直下にある画像を読み込んでループ表示をするだけの簡単なお仕事です。

というわけで、まずは準備。
以下の画像をSD直下に保存します。

手書きの画像。ちょっとかわいい(笑)
↑こういうのを自画自賛という。

ちなみに完成画面はこんな簡易なものになります。

まずはSDカード直下に保存されている画像を取得するメソッドを作成します。
このときは".png"で判断しています。
.jpegなどは容赦なく無視。

  1. private ArrayAdapter<string> getImageFile() {  
  2.  // adapter の作成  
  3.  ArrayAdapter<string> adapter = new ArrayAdapter<string>(this,  
  4.    android.R.layout.simple_spinner_item);  
  5.   
  6.  // SDカードのディレクトリを取得  
  7.  File directory = Environment.getExternalStorageDirectory();  
  8.   
  9.  // SDカードの一番上からファイルを取得  
  10.  File[] files = directory.listFiles();  
  11.   
  12.  // adapterにファイルパスを追加  
  13.  for (int i = 0; i < files.length; i++) {  
  14.   // pngを追加  
  15.   if (files[i].getName().endsWith(".png")) {  
  16.    adapter.add(files[i].getPath());  
  17.   }  
  18.  }  
  19.   
  20.  return adapter;  
  21. }  
  22. </string></string></string>  
あとで使うのでadapterで返しています。
取得したSDの画像をスピナーへ。
SD直下になにも画像がなかったときは強制的にアプリを終了させてみました(おい)。

  1. // SDのファイル取得  
  2. mFileSpinner = (Spinner) findViewById(R.id.fileSelectSpinner);  
  3.   
  4. // adapterの作成  
  5. mFileSpinner.setAdapter(getImageFile());  
  6. mFileSpinner.setOnItemSelectedListener(this);  
  7.   
  8. // ファイルがなかったときはアプリケーション終了  
  9. if(mFileSpinner.getChildCount() == 0) {  
  10.  Toast.makeText(this"File Nothing! application close...", Toast.LENGTH_LONG).show();  
  11.  finish();  
  12. }  
スタートボタンを押すとはじまります。

最初にmIsSlideShowというフラグをつくっておいてSTART/STOPを制御します。

  1. private boolean mIsSlideShow = false;  
では、スタートボタンの実装へ。

  1. public void onClickShowButton(View view) {  
  2.   
  3.  Button showButton = (Button) findViewById(R.id.showButton);  
  4.   
  5.  if (mIsSlideShow) {  
  6.   // ストップ  
  7.   mHandler.sendEmptyMessage(0);  
  8.   showButton.setText("START");  
  9.  } else {  
  10.   // スタート  
  11.   mCurrentPosition = mFileSpinner.getSelectedItemPosition();  
  12.   showImageFile(mFileSpinner.getSelectedItemPosition());  
  13.   showButton.setText("STOP");  
  14.   mIsSlideShow = true;  
  15.   Thread thread = new Thread(this);  
  16.   thread.start();  
  17.  }  
  18.   
  19. }  
スレッドで制御しております。なぜなら、途中でストップを押すために。
その前に画像を表示させるメソッドを。

  1. private void showImageFile(int position) {  
  2.   
  3.  String selectFilePath = (String) mFileSpinner  
  4.    .getItemAtPosition(position);  
  5.   
  6.  Bitmap bitmap = BitmapFactory.decodeFile(selectFilePath);  
  7.  mImageCanvas.setImageBitmap(bitmap);  
  8.   
  9. }  
スレッドはこうなります。

  1. @Override  
  2. public void run() {  
  3.  while (mIsSlideShow) {  
  4.   try {  
  5.    // スリープ(10秒)  
  6.    Thread.sleep(10000);  
  7.   } catch (Exception e) {  
  8.    Log.e(TAG, "error!!");  
  9.   }  
  10.   
  11.   Log.i(TAG, String.valueOf(mCurrentPosition));  
  12.   
  13.   // 画像の変更  
  14.   if (mCurrentPosition == mFileSpinner.getCount() - 1) {  
  15.    // 先頭へ  
  16.    mCurrentPosition = 0;  
  17.   } else {  
  18.    mCurrentPosition++;  
  19.   }  
  20.   
  21.   mHandler.post(new Runnable() {  
  22.    @Override  
  23.    public void run() {  
  24.     showImageFile(mCurrentPosition);  
  25.    }  
  26.   });  
  27.   
  28.  }  
  29.   
  30. }  
  31.   
  32. private Handler mHandler = new Handler() {  
  33.  public void handleMessage(Message msg) {  
  34.   // 終了  
  35.   mIsSlideShow = false;  
  36.  }  
  37.   
  38. };  
ストップが押されるまで画像がループされます。

というわけで今日のソースはこちら。

  1. package jp.co.mogakana.slideshow;  
  2.   
  3. import java.io.File;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.BroadcastReceiver;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.content.IntentFilter;  
  10. import android.graphics.Bitmap;  
  11. import android.graphics.BitmapFactory;  
  12. import android.os.Bundle;  
  13. import android.os.Environment;  
  14. import android.os.Handler;  
  15. import android.os.Message;  
  16. import android.util.Log;  
  17. import android.view.View;  
  18. import android.widget.AdapterView;  
  19. import android.widget.AdapterView.OnItemSelectedListener;  
  20. import android.widget.ArrayAdapter;  
  21. import android.widget.Button;  
  22. import android.widget.ImageView;  
  23. import android.widget.Spinner;  
  24. import android.widget.Toast;  
  25.   
  26. public class SlideShowActivity extends Activity implements  
  27.   OnItemSelectedListener, Runnable {  
  28.   
  29.  private static final String TAG = "SlideShow";  
  30.   
  31.  private int mCurrentPosition;  
  32.   
  33.  private Spinner mFileSpinner;  
  34.  private ImageView mImageCanvas;  
  35.   
  36.  private boolean mIsSlideShow = false;  
  37.   
  38.  @Override  
  39.  public void onCreate(Bundle savedInstanceState) {  
  40.   super.onCreate(savedInstanceState);  
  41.   setContentView(R.layout.main);  
  42.   
  43.   mImageCanvas = (ImageView) findViewById(R.id.slideShowImageView);  
  44.   
  45.   // SDのファイル取得  
  46.   mFileSpinner = (Spinner) findViewById(R.id.fileSelectSpinner);  
  47.   // adapterの作成  
  48.   mFileSpinner.setAdapter(getImageFile());  
  49.   
  50.   mFileSpinner.setOnItemSelectedListener(this);  
  51.     
  52.     
  53.   // ファイルがなかったときはアプリケーション終了  
  54.   if(mFileSpinner.getChildCount() == 0) {  
  55.       Toast.makeText(this"File Nothing! application close...", Toast.LENGTH_LONG).show();  
  56.       finish();  
  57.   }  
  58.     
  59.   
  60.  }  
  61.   
  62.  public void onClickShowButton(View view) {  
  63.   
  64.   Button showButton = (Button) findViewById(R.id.showButton);  
  65.   
  66.   if (mIsSlideShow) {  
  67.    // ストップ  
  68.    mHandler.sendEmptyMessage(0);  
  69.    showButton.setText("START");  
  70.   } else {  
  71.    // スタート  
  72.    mCurrentPosition = mFileSpinner.getSelectedItemPosition();  
  73.    showImageFile(mFileSpinner.getSelectedItemPosition());  
  74.    showButton.setText("STOP");  
  75.    mIsSlideShow = true;  
  76.    Thread thread = new Thread(this);  
  77.    thread.start();  
  78.   }  
  79.   
  80.  }  
  81.   
  82.  private void showImageFile(int position) {  
  83.   
  84.   String selectFilePath = (String) mFileSpinner  
  85.     .getItemAtPosition(position);  
  86.   
  87.   Bitmap bitmap = BitmapFactory.decodeFile(selectFilePath);  
  88.   mImageCanvas.setImageBitmap(bitmap);  
  89.   
  90.  }  
  91.   
  92.  private ArrayAdapter<string> getImageFile() {  
  93.   // adapter の作成  
  94.   ArrayAdapter<string> adapter = new ArrayAdapter<string>(this,  
  95.     android.R.layout.simple_spinner_item);  
  96.   
  97.   // SDカードのディレクトリを取得  
  98.   File directory = Environment.getExternalStorageDirectory();  
  99.   
  100.   // SDカードの一番上からファイルを取得  
  101.   File[] files = directory.listFiles();  
  102.   
  103.   // adapterにファイルパスを追加  
  104.   for (int i = 0; i < files.length; i++) {  
  105.    // pngを追加  
  106.    if (files[i].getName().endsWith(".png")) {  
  107.     adapter.add(files[i].getPath());  
  108.    }  
  109.   }  
  110.   
  111.   return adapter;  
  112.  }  
  113.   
  114.  @Override  
  115.  public void onItemSelected(AdapterView<!----> arg0, View arg1, int position,  
  116.    long arg3) {  
  117.   
  118.  }  
  119.   
  120.  @Override  
  121.  public void onNothingSelected(AdapterView<!----> arg0) {  
  122.   Toast.makeText(this"File Nothing!", Toast.LENGTH_LONG).show();  
  123.  }  
  124.   
  125.  @Override  
  126.  public void run() {  
  127.   while (mIsSlideShow) {  
  128.    try {  
  129.     // スリープ(10秒)  
  130.     Thread.sleep(10000);  
  131.    } catch (Exception e) {  
  132.     Log.e(TAG, "error!!");  
  133.    }  
  134.   
  135.    Log.i(TAG, String.valueOf(mCurrentPosition));  
  136.   
  137.    // 画像の変更  
  138.    if (mCurrentPosition == mFileSpinner.getCount() - 1) {  
  139.     // 先頭へ  
  140.     mCurrentPosition = 0;  
  141.    } else {  
  142.     mCurrentPosition++;  
  143.    }  
  144.   
  145.    mHandler.post(new Runnable() {  
  146.     @Override  
  147.     public void run() {  
  148.      showImageFile(mCurrentPosition);  
  149.     }  
  150.    });  
  151.   
  152.   }  
  153.   
  154.  }  
  155.   
  156.  private Handler mHandler = new Handler() {  
  157.   public void handleMessage(Message msg) {  
  158.    // 終了  
  159.    mIsSlideShow = false;  
  160.   }  
  161.   
  162.  };  
  163.   
  164.  @Override  
  165.  protected void onResume() {  
  166.   super.onResume();  
  167.     
  168.  }  
  169.   
  170.  @Override  
  171.  protected void onPause() {  
  172.   super.onPause();  
  173.  }  
  174.   
  175. }  
  176. </string></string></string>  
適当に書いたんだけど、けっこう絵がかわいいと自画自賛中。

2011年9月2日金曜日

[Android] GALAPAGOS メディアタブレットのUSBドライバについて

ADB USBドライバは
ここ。

ソフトウェアダウンロード

でかいタイプ(いちばんおおきいやつ)も
これでいけます。

ねむりたい。ねむりたい。

2011年8月20日土曜日

[Windows Phone 7] アプリケーションの作成と起動

簡単に。
まずはVisualStdio2010(WP)を起動します。

で、見たことある感じの画面から
NEW Projectを選択するとこのような画面が出ます。


















なぜ、VBなんだ・・・。
というツッコミのもと、下のC#を選択します。
おそらくVBでもつくれなくはないのですが、エラーがでてとれなかったので(失格)、とりあえずこちらを。

















プロジェクト名に適当な名前を入れて(もちろんこのままでもいい)
OKを押すだけ。

あとは実行ボタンを押して待てばエミュレータが起動して
なにやらメッセージがでます。

終了。


というのもおもしろくないので
今回はコードはいじらずにデザイン画面からラベルを選択して
文字だけをいじってみました。

で、こうなる。























昔のHello Androidを思い出しますね、はい。

コードを書くときはそれぞれの配置したUIでクリックするなりなんだかんだりで
VisualStdion感満載でできるかとおもいます。

続きは後日。

[Windows Phone 7] 開発環境を整える

やってみることにしました。

OSはwindows7で。
Windows Phone 開発者向け技術情報 に飛ぶ

アプリケーション開発のところに
Windows Phone SDK 7.1 Beta 2
というリンクがあるのでジャンプ。

vm_web2.exe

をダウンロード。
ダウンロードしたファイルを実行するとインストーラーが走るのでまつべし。
私のパソコンはそんなに悪い性能ではないのですが、けっこうまたされました。
なのでコーヒー片手に本でも用意しておくとよいでしょう。

再起動を促されるのでおとなしく再起動をしましょう。


つづいては
Windows Phone Developer Tools RTW
のインストール。

余談ですが、この順序は逆なので・・・。(どちらからでもいいかとおもいますが)

vm_web.exe

をダウンロードして実行します。
こちらも時間がかかるので紅茶をのみながらのほほんとまっていましょう。

こちらは再起動は促されない様子です。

起動するとWindowsPhone用のVisualStudioが起動します。
外見は本当にVisualStudioなので(あたりまえだ)、触ったことある人は大体直感でわかるんじゃないかとおもいます。

2011年8月13日土曜日

[お知らせ] 日本Androidの会 関西支部のLTにでます。

9月3日にある
「日本Androidの会 関西支部勉強会」
でLTをやります。

もう人数埋まってますが、よかったらどうぞ。
ATNDより

LTやりますといったのはいいけど、ネタはこれからつくるのだったりする。
開発系のことをしゃべります。
あたまのなかで「あれをしゃべるかー」というのは考えているのですが

うーん。

5分で関西の人々の心をつかめるかはわからないですね。

ちなみに色々な都合上名前が「高田純三」になっています。
たぶんニッカポッカに木刀だな。

[Android] 007SH スクリーンショットの撮り方

いつのまにか007SH Jでスクリーンショットがとれるようになっておりました。

撮り方
取りたい画面で
終話キー(または側面のロックキー)+ ホームキー

ホームキーはさりげなく下にあってよくミスってうってしまうあのキーです。
0の下。

単体でスクリーンショットがとれるのはかなり便利。
友達とやりとりするときとか。

2011年8月6日土曜日

[Android] 2.1以上の電話帳(つまりContacts)とたたかってみるんだぜ その1

電話帳って2.1から変更されたんですよね。
ゆえにそんなにリファレンスサイトがないので自分でどーこーしてみることにした。
某会議でよく電話帳が話題になるので
まー、興味がでたっていえばでたんですけど。

Androidでは電話帳DBなるものが標準で搭載されている。
/data/data/com.android.providers.contacts/databases/contacts2.db
という場所にあったりする。
実際にデータをpullなどでぬいてきて
SQLite3のビューアーとかでみるとたしかにデータがはいっている。

が、これがすごくわかりづらい。
一回に解説したいですが、私にもわかってない箇所があるので
まー、それはゆっくりと。
とりあえず2.1からでは「ごっそりと仕組みが変わった」ということを覚えていただきたいです。
覚えなくてもいいけど。

では、簡単につかってみましょう。
前提条件として電話帳にこんな感じのデータをいれておきます。



















これは標準電話帳の画面です。
で、最終的にこんな感じにする。



















今回はかるーくテストなんで名前だけの表示にしています。
本来なら、下に電話番号をだすなり、メアドだすなり好きにしていいんですが
仕事中の休み時間にできることは限られているので(1時間しかない)。
時間があればそのうちハイパーなものをつくりたんですが、はてさて。

では本日のコードです。

まずはレイアウトのXMLを。

  1. <!--xml version="1.0" encoding="utf-8"?-->  
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">  
  3.     <listview android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/listView"></listview>  
  4. </linearlayout>  

簡単にListViewだけを表示しているのでこれだけです。
つづいてはこちらに名前を入れるコード。

  1. import android.app.Activity;  
  2. import android.database.Cursor;  
  3. import android.os.Bundle;  
  4. import android.provider.ContactsContract;  
  5. import android.widget.ArrayAdapter;  
  6. import android.widget.ListView;  
  7.   
  8. public class AddressListActivity extends Activity {  
  9.    
  10.  private ListView mListView;  
  11.    
  12.  @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.address_list);  
  16.           
  17.         // 表示  
  18.         mListView = (ListView) findViewById(R.id.listView);  
  19.         mListView.setAdapter(displayNameList());  
  20.     
  21.  }  
  22.    
  23.  // DBから取り出してごにょっとする  
  24.  private ArrayAdapter<string> displayNameList() {  
  25.     
  26.   // DBアクセス  
  27.   databaseAccess access = new databaseAccess(this);  
  28.   Cursor cursor = access.selectAllAddress();  
  29.     
  30.   cursor.moveToFirst();  
  31.   ArrayAdapter<string> adapter = new ArrayAdapter<string>(this,android.R.layout.simple_list_item_1);  
  32.     
  33.   // Contactsのデータを管理しているRAW_CONACT_ID  
  34.   int idIndex = cursor.getColumnIndexOrThrow(ContactsContract.Data.RAW_CONTACT_ID);  
  35.   // 表示名  
  36.   int nameIndex = cursor.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME);  
  37.   // idにとりあえずの初期値を入れておく  
  38.   int id = 0;  
  39.     
  40.   while (!cursor.isAfterLast()) {  
  41.    // idが変わったら次の人  
  42.    if(id != cursor.getInt(idIndex)) {  
  43.     // idの入れ替え  
  44.     id = cursor.getInt(idIndex);  
  45.     // 表示名取得  
  46.     adapter.add(cursor.getString(nameIndex));  
  47.       
  48.       
  49.    }  
  50.    cursor.moveToNext();  
  51.   }  
  52.     
  53.   cursor.close();  
  54.     
  55.   return adapter;  
  56.     
  57.     
  58.     
  59.  }  
  60.    
  61. }  
  62. </string></string></string>  

コメントいれてあるのですが、実は上のコードにはDBにアクセスする処理はございません。
アクセスするにはこちらのコードを。
別にクラスを分ける必要性はなかったのですが、
あとあと入力とかを拡張しようと思っていたのでわけました。

  1. import android.content.Context;  
  2. import android.database.Cursor;  
  3. import android.net.Uri;  
  4. import android.provider.ContactsContract;  
  5.   
  6. public class databaseAccess {  
  7.    
  8.  private Context context;  
  9.  private Uri uri = ContactsContract.Data.CONTENT_URI;  
  10.    
  11.  // コンストラクタ  
  12.  public databaseAccess(Context context){  
  13.   this.context = context;  
  14.     
  15.  }  
  16.    
  17.  /** 
  18.   * DB全件返しメソッド 
  19.   * @return 
  20.   */  
  21.  public Cursor selectAllAddress() {  
  22.   return context.getContentResolver().query(uri, nullnullnullnull);  
  23.  }  
  24.   
  25. }  

クエリのつかいかたですが、

  1. Cursor android.content.ContentResolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)  

という記述がDevelopersなんとかっていう解説書(もう忘れた)にあります。
場所を指定して、取り出すものを指定。さらに条件・・・といったところでしょうか。
今回は簡易なのでいやでも全件返すようにしています。

全件返すことでもちろん名前以外にも電話番号まで帰ってきているので

  1. while (!cursor.isAfterLast()) {  
  2.  // idが変わったら次の人  
  3.  if(id != cursor.getInt(idIndex)) {  
  4.   // idの入れ替え  
  5.   id = cursor.getInt(idIndex);  
  6.   // 表示名取得  
  7.   adapter.add(cursor.getString(nameIndex));  
  8.     
  9.     
  10.  }  
  11.  cursor.moveToNext();  
  12. }  

このあたりのところでいろいろ分岐させています。
IDは一人につき1つなので、そのIDが切り替わったら次の人。
同じIDが名前を2回もっていることもあるのでこういう重複チェックをかけています。
なぜ名前を2回もっているのかというと・・・

「ID」「表示名」「電話番号」
「ID」「表示名」「苗字」

というようなデータ構造になっているためです。
表示名は何回もはいってくるのですね(汗)


なのでまわりくどいコードになっています。
このあたりは私の調査不足なのでおいおいかっこいいコードに(そりゃもう鼻血がでるほど)していけたらいいなーとおもいますがな。


そんな感じで第一回電話帳会議終了。

ではもどるぞ!!だいじゅうよんてい(ry)

はい、仕事します。