2011年9月22日木曜日

暗黙のインテントとContent-Type

色々と躓きながら作成しています。
今回は、暗黙のインテントを飛ばす時に 拡張子でContent-Typeを色々指定する必要があるのですが、 ifとかで判別して一々やるのはめんどいなぁってことで、 ちょっとしたDBとクラスを作成してみました。 拡張子とContent-Typeを紐付けしたDBを作成して、 暗黙のインテントを飛ばす時にDBからContent-Typeを取得してやろうという試みです。
まずは拡張子とContent-Typeを紐付けたDBのソースです。

public class ContentTypeDB {
 /**
  * DBの要素
  * _EXT:拡張子
  * _TYPE:content-type文字列
  */
 public interface DataColumns extends BaseColumns {
  public static final String DISPLAY_NAME ="_display_name";
  public static final String _EXT = "_EXTENSION";
  public static final String _TYPE = "_TYPE";
 }
 
 private SQLiteDatabase contentTypeDB;
 private static final String DATABASE_TABLE = "IntentParamTable";
 
 private static class DatabaseHelper extends SQLiteOpenHelper {
  private static final String DATABASE_NAME = "IntentParamList";
  private static final int DATABASE_VERSION =1;
  //初期化判別用
  private boolean notInitialize = false;
  
  private static final String DATABASE_CREATE = 
   "create table " + 
   DATABASE_TABLE + " (" +
   DataColumns._EXT + " text primary key, " +
   DataColumns._TYPE + " text not null" +
   ");";
   
  public DatabaseHelper(Context context) {
   super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }
  
  @Override
  public void onCreate(SQLiteDatabase db) {
   db.execSQL(DATABASE_CREATE);
   //DBがない場合、trueにしておく
   notInitialize = true;
  }
  
  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   db.execSQL("DROP TABLE IF EXIST IntentParamList");
   onCreate(db);
  }
  
  /**
   * DBの初期化を行う
   * @param content
   */
  public void initialize(ContentTypeDB content){
   if(notInitialize){
    //DBを作成した場合、デフォルトのContent-Typeを設定する
    ContentTypeHelper.setDefaultContentType(content);
   }
  }
 }

 /**
  * コンストラクタ
  * @param context
  */
 public ContentTypeDB(Context context){
  DatabaseHelper dbHelper = new DatabaseHelper(context);
  contentTypeDB = dbHelper.getWritableDatabase();
  //DBの初期化を試みる
  dbHelper.initialize(this);
 }
 
 /**
  * 指定要素を削除する
  * @param ipAddress
  * @return
  */
 public int delete(ContentElement elem){
  int count = contentTypeDB.delete(DATABASE_TABLE,
    DataColumns._EXT + " = '" + elem.getExtension()+"'",null);
  return count;
 }
 
 /**
  * 要素を追加する
  * @param element
  * @return
  */
 public int registerElement(ContentElement element){
  if(!existElement(element.getExtension())){
   insert(element);
  }
  return 0;
 }
 
 /**
  * DB内の要素を全て取得する
  * @return
  */
 public ArrayList getAllElements(){
  ArrayList elements = new ArrayList();
  Cursor c = query(null, null, null, DataColumns._EXT + " asc");
  if(c.moveToFirst()){
   do {
    elements.add(new ContentElement(
      c.getString(c.getColumnIndex(DataColumns._EXT)),
      c.getString(c.getColumnIndex(DataColumns._TYPE))
      ));
   } while(c.moveToNext());
  }
  return elements;
 }
 
 public void close(){
  contentTypeDB.close();
 }
 
 public Cursor query(String[] projection, String selection,
   String[] selectionArgs, String sortOrder) {
  SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
  sqlBuilder.setTables(DATABASE_TABLE);
  
  if(sortOrder == null || sortOrder == ""){
   sortOrder = DataColumns._EXT;
  }
  
  Cursor c = sqlBuilder.query(contentTypeDB, projection, selection,
    selectionArgs, null, null, sortOrder);
  return c;
 }
 
 /**
  * DBを拡張子で検索し、Content-Type文字列を取得する
  * @param extension 検索対象の拡張子文字列
  * @return 見つかったContent-Type文字列。DBにない場合nullが返却される。
  */
 public String getType(String extension){
  Cursor c = query(null, DataColumns._EXT+"= \""+extension+"\"", null, null);
  String retType = null;
  if(c.moveToFirst()){
   retType = c.getString(c.getColumnIndex(DataColumns._TYPE));
  }
  return retType;
 }
 
 /**
  * トランザクション開始
  */
 public void startTransaction(){
  contentTypeDB.beginTransaction();
 }
 
 /**
  * コミット
  */
 public void commit(){
  contentTypeDB.setTransactionSuccessful();
 }
 
 /**
  * トランザクション終了
  */
 public void endTransaction(){
  contentTypeDB.endTransaction();
 }

 /**
  * DB内に指定要素が存在するか確認する
  * @param extension
  * @return
  */
 private boolean existElement(String extension){
  boolean exist = false;
  String [] targetCol = {DataColumns._EXT};
  Cursor c = query(targetCol, 
    DataColumns._EXT +"= \""+ extension+"\"", null, null);
  if(c.moveToFirst()){
   exist = true;
  }
  c.close();
  return exist;
 }

 private long insert(ContentElement element){
  long rowID = contentTypeDB.insert(DATABASE_TABLE, "", element.getContentValues());
  if(rowID>0){
   return rowID;
  }
  throw new SQLException();
 }
}


このContentTypeDBクラスのインスタンスを作成することでDBを作成します。 ここで、DBのCreate時にContentTypeHelperクラスを使ってデフォルトの値を DBに突っ込んでます。
ContentTypeHelperクラスのソースはこちらです。

public class ContentTypeHelper {
 //拡張子とContent-Typeのデフォルト値
 static final String[][] defaultTypeArray = {
  {"application/envoy", "evy"},
  {"application/fractals", "fif"},
  {"application/futuresplash", "spl"},
  {"application/hta", "hta"},
  {"application/internet-property-stream", "acx"},
  {"application/mac-binhex40", "hqx"},
  {"application/msword", "doc"},
  {"application/msword", "dot"},
  {"application/octet-stream", "bin"},
  {"application/octet-stream", "class"},
  {"application/octet-stream", "dms"},
  {"application/octet-stream", "exe"},
  {"application/octet-stream", "lha"},
  {"application/octet-stream", "lzh"},
  {"application/oda", "oda"},
  {"application/olescript", "axs"},
  {"application/pdf", "pdf"},
  {"application/pics-rules", "prf"},
  {"application/pkcs10", "p10"},
  {"application/pkix-crl", "crl"},
  {"application/postscript", "ai"},
  {"application/postscript", "eps"},
  {"application/postscript", "ps"},
  {"application/rtf", "rtf"},
  {"application/set-payment-initiation", "setpay"},
  {"application/set-registration-initiation", "setreg"},
  {"application/vnd.ms-excel", "xla"},
  {"application/vnd.ms-excel", "xlc"},
  {"application/vnd.ms-excel", "xlm"},
  {"application/vnd.ms-excel", "xls"},
  {"application/vnd.ms-excel", "xlt"},
  {"application/vnd.ms-excel", "xlw"},
  {"application/vnd.ms-outlook", "msg"},
  {"application/vnd.ms-pkicertstore", "sst"},
  {"application/vnd.ms-pkiseccat", "cat"},
  {"application/vnd.ms-pkistl", "stl"},
  {"application/vnd.ms-powerpoint", "pot"},
  {"application/vnd.ms-powerpoint", "pps"},
  {"application/vnd.ms-powerpoint", "ppt"},
  {"application/vnd.ms-project", "mpp"},
  {"application/vnd.ms-works", "wcm"},
  {"application/vnd.ms-works", "wdb"},
  {"application/vnd.ms-works", "wks"},
  {"application/vnd.ms-works", "wps"},
  {"application/winhlp", "hlp"},
  {"application/x-bcpio", "bcpio"},
  {"application/x-cdf", "cdf"},
  {"application/x-compress", "z"},
  {"application/x-compressed", "tgz"},
  {"application/x-cpio", "cpio"},
  {"application/x-csh", "csh"},
  {"application/x-director", "dcr"},
  {"application/x-director", "dir"},
  {"application/x-director", "dxr"},
  {"application/x-dvi", "dvi"},
  {"application/x-gtar", "gtar"},
  {"application/x-gzip", "gz"},
  {"application/x-hdf", "hdf"},
  {"application/x-internet-signup", "ins"},
  {"application/x-internet-signup", "isp"},
  {"application/x-iphone", "iii"},
  {"application/x-javascript", "js"},
  {"application/x-latex", "latex"},
  {"application/x-msaccess", "mdb"},
  {"application/x-mscardfile", "crd"},
  {"application/x-msclip", "clp"},
  {"application/x-msdownload", "dll"},
  {"application/x-msmediaview", "m13"},
  {"application/x-msmediaview", "m14"},
  {"application/x-msmediaview", "mvb"},
  {"application/x-msmetafile", "wmf"},
  {"application/x-msmoney", "mny"},
  {"application/x-mspublisher", "pub"},
  {"application/x-msschedule", "scd"},
  {"application/x-msterminal", "trm"},
  {"application/x-mswrite", "wri"},
  {"application/x-netcdf", "cdf"},
  {"application/x-netcdf", "nc"},
  {"application/x-perfmon", "pma"},
  {"application/x-perfmon", "pmc"},
  {"application/x-perfmon", "pml"},
  {"application/x-perfmon", "pmr"},
  {"application/x-perfmon", "pmw"},
  {"application/x-pkcs12", "p12"},
  {"application/x-pkcs12", "pfx"},
  {"application/x-pkcs7-certificates", "p7b"},
  {"application/x-pkcs7-certificates", "spc"},
  {"application/x-pkcs7-certreqresp", "p7r"},
  {"application/x-pkcs7-mime", "p7c"},
  {"application/x-pkcs7-mime", "p7m"},
  {"application/x-pkcs7-signature", "p7s"},
  {"application/x-sh", "sh"},
  {"application/x-shar", "shar"},
  {"application/x-shockwave-flash", "swf"},
  {"application/x-stuffit", "sit"},
  {"application/x-sv4cpio", "sv4cpio"},
  {"application/x-sv4crc", "sv4crc"},
  {"application/x-tar", "tar"},
  {"application/x-tcl", "tcl"},
  {"application/x-tex", "tex"},
  {"application/x-texinfo", "texi"},
  {"application/x-texinfo", "texinfo"},
  {"application/x-troff", "roff"},
  {"application/x-troff", "t"},
  {"application/x-troff", "tr"},
  {"application/x-troff-man", "man"},
  {"application/x-troff-me", "me"},
  {"application/x-troff-ms", "ms"},
  {"application/x-ustar", "ustar"},
  {"application/x-wais-source", "src"},
  {"application/x-x509-ca-cert", "cer"},
  {"application/x-x509-ca-cert", "crt"},
  {"application/x-x509-ca-cert", "der"},
  {"application/ynd.ms-pkipko", "pko"},
  {"application/zip", "zip"},
  {"audio/basic", "au"},
  {"audio/basic", "snd"},
  {"audio/mid", "mid"},
  {"audio/mid", "rmi"},
  {"audio/mpeg", "mp3"},
  {"audio/x-aiff", "aif"},
  {"audio/x-aiff", "aifc"},
  {"audio/x-aiff", "aiff"},
  {"audio/x-mpegurl", "m3u"},
  {"audio/x-pn-realaudio", "ra"},
  {"audio/x-pn-realaudio", "ram"},
  {"audio/x-wav", "wav"},
  {"image/bmp", "bmp"},
  {"image/cis-cod", "cod"},
  {"image/gif", "gif"},
  {"image/ief", "ief"},
  {"image/jpeg", "jpe"},
  {"image/jpeg", "jpeg"},
  {"image/jpeg", "jpg"},
  {"image/pipeg", "jfif"},
  {"image/svg+xml", "svg"},
  {"image/tiff", "tif"},
  {"image/tiff", "tiff"},
  {"image/x-cmu-raster", "ras"},
  {"image/x-cmx", "cmx"},
  {"image/x-icon", "ico"},
  {"image/x-portable-anymap", "pnm"},
  {"image/x-portable-bitmap", "pbm"},
  {"image/x-portable-graymap", "pgm"},
  {"image/x-portable-pixmap", "ppm"},
  {"image/x-rgb", "rgb"},
  {"image/x-xbitmap", "xbm"},
  {"image/x-xpixmap", "xpm"},
  {"image/x-xwindowdump", "xwd"},
  {"message/rfc822", "mht"},
  {"message/rfc822", "mhtml"},
  {"message/rfc822", "nws"},
  {"text/css", "css"},
  {"text/h323", "323"},
  {"text/html", "htm"},
  {"text/html", "html"},
  {"text/html", "stm"},
  {"text/iuls", "uls"},
  {"text/plain", "bas"},
  {"text/plain", "c"},
  {"text/plain", "h"},
  {"text/plain", "txt"},
  {"text/richtext", "rtx"},
  {"text/scriptlet", "sct"},
  {"text/tab-separated-values", "tsv"},
  {"text/webviewhtml", "htt"},
  {"text/x-component", "htc"},
  {"text/x-setext", "etx"},
  {"text/x-vcard", "vcf"},
  {"video/mpeg", "mp2"},
  {"video/mpeg", "mpa"},
  {"video/mpeg", "mpe"},
  {"video/mpeg", "mpeg"},
  {"video/mpeg", "mpg"},
  {"video/mpeg", "mpv2"},
  {"video/quicktime", "mov"},
  {"video/quicktime", "qt"},
  {"video/x-la-asf", "lsf"},
  {"video/x-la-asf", "lsx"},
  {"video/x-ms-asf", "asf"},
  {"video/x-ms-asf", "asr"},
  {"video/x-ms-asf", "asx"},
  {"video/x-msvideo", "avi"},
  {"video/x-sgi-movie", "movie"},
  {"x-world/x-vrml", "flr"},
  {"x-world/x-vrml", "vrml"},
  {"x-world/x-vrml", "wrl"},
  {"x-world/x-vrml", "wrz"},
  {"x-world/x-vrml", "xaf"},
  {"x-world/x-vrml", "xof"}
 };
 
 /**
  * DBにデフォルト値をセットする
  * @param db
  */
 public static void setDefaultContentType(ContentTypeDB db){
  ContentElement element;
  
  db.startTransaction();
  for(int i=0; i< defaultTypeArray.length; i++){
   element = new ContentElement(defaultTypeArray[i][1], defaultTypeArray[i][0]);
   db.registerElement(element);
  }
  db.commit();
  db.endTransaction();
 }
}


こんな感じ。デフォルトの配列を作成するのがちょっと面倒ですがしょうがないです。 これだけできれば後はこいつを使ってインテントを投げましょう。
今回は暗黙のインテントを投げる用のクラスを作成しています。 ソースは以下。

/**
 * 暗黙のインテント呼び出し用クラス
 *
 */
public class IntentHelper {
 /**
  * @param target 受け渡すファイル
  * @param act 呼び出し元アクティビティ
  */
 static public void callIntentByFile(File target, Activity act){
  String fileExtension = getExtension(target.getName());
  ContentTypeDB db = new ContentTypeDB(act.getApplicationContext());
  String contentType = db.getType(fileExtension);
  db.close();
  if(contentType!=null){
   callIntent(act,target, getActionType(fileExtension), contentType);
  }
 }
 
 /**
  * 拡張子取得メソッド
  * @param path
  * @return
  */
 static protected String getExtension(String path){
  int pos = path.lastIndexOf(".");
  String ext = "";
  if(pos != -1){
   pos++;
   ext = path.substring(pos);
  }
  return ext;
 }
 
 /**
  * 取りあえず今はACTION_VIEW固定
  */
 static private String getActionType(String fileExtension){
  return Intent.ACTION_VIEW;
 }
 
 static private void callIntent(Activity calleeAct,File file,String action,String contentType){
  if(file==null||action==null||contentType==null){
   return;
  }
  Intent intent = new Intent();
  intent.setAction(action);
  intent.setDataAndType(Uri.fromFile(file),contentType);
  calleeAct.startActivity(intent);
 }
}



IntentHelperクラスのcallIntentByFileメソッドに受け渡すファイルと、自アクティビティを指定して 呼び出せばアラ不思議、多分候補のアプリ選択ダイアログが出てくるはずです。はずです。
後は独自に拡張子を増やしたりなんだりしてやればいいはず。そんな感じ。

10/29 追記

初期化時のデフォルト値設定でかなり時間がかかってましたが、 transactionを追加することで解消できました。 ソースのContentTypeDbクラスとContentTypeHelperクラスが変更されています。 データベース関係には今まで触れたことがあまりなかったからな。。。 ちょっとは勉強しとかないと。

2011年9月14日水曜日

イメージをグレースケールにしたりカラーに戻したり

今回はイメージボタンの画像を動的にグレースケールにしたりカラーに戻したりと いうようなことをやってみました。 使用するクラスは、ColorMatrixColorFilterクラス。
ColorMatrixクラスのインスタンスメソッドのsetSaturationで HSV色空間のS(彩度)を0に設定したマトリクスを作成します。
そのマトリクスを使ってColorMatrixColorFilterを生成することで、 グレースケール用のフィルタを作成しています。
後は、イベントをトリガーに対象のイメージボタンの ColorFilterに設定したり、nullで取り除いたりすることで、 動的にグレースケールとの切り替えが行えます。

以下適当なサンプルコード


    private ColorMatrixColorFilter grayScaleFilter;
    private ImageButton imgBtn;

    private void initialize(){
        imgBtn = (ImageButton) findViewById(id.imageButtonA);
        ColorMatrix matrix = new ColorMatrix();
        matrix.setSaturation(0);
        grayScaleFilter = new ColorMatrixColorFilter(matrix);
    }

    public void changeGrayScaleMode(){
        imgBtn.setColorFilter(grayScaleFilter);
    }
    public void changeColorMode(){
        imgBtn.setColorFilter(null);
    }


追記
厳密に言うと彩度を0にするのと、グレースケールとは違うのだけどまぁいいか。

2011年9月3日土曜日

進捗~ その2

作成してるもののメモその2です。 前回から半月しますが、なかなか進みませんね。 現在は下のような感じになってます。
左右で、接続先PCのファイルと、ローカルのファイルが表示されるようになってます。 あと、ローカルファイルの画像閲覧、ZIP/RARファイル内の閲覧とかができるようにもなってます。
音楽ファイルの再生時に表示される画面です。 ダウンロード最中でも再生されるようになっています。 時間がnullになっていますが気にしないでください。1秒後にはきちんと表示されます。
一応ファイル転送機能とかもつけてる最中ですが、GUIて難しいですね。 あとは、ファイルリスト画面の表示/非表示機能をつけて、転送中の画面つけて、 ダイアログ出したり送信状況出したり、 うーん、まだまだですね。