ドコモメールバックアップ/Ver1.2.1を公開しました

自動実行機能が動作していなかった不具合の修正です

Quick電話帳 Ver8.3.0 released

ライン表示とタイル表示のレイアウトを変更しました
いくつかの環境で正常に電話帳が表示されない不具合を修正しました
高画質写真が存在する場合を高画質写真を利用するようにしました
タイル・詳細の写真表示を大きくしました

ドコモメールバックアップ Ver1.2を公開しました

大きな変更点はログの表示に対応したことですがそれ以外にも下記の修正が入っています。

アプリ本体の修正です。
端末の解像度によってアイコンサイズが大きめになる不具合を修正しました
アプリのライブラリチェックの不具合を修正しました
タスクの日数を0〜20まで増やしました(0にすると日付チェックを行いません)
タスク一覧での送信元ラベルとターゲットラベルが逆になっていた不具合を修正しました

ライブラリの修正です
通知アイコンのサイズが最適でない問題を修正しました
処理終了後自動的に通知を消すようにしました

両方のバージョンアップをお願いいたします。

ドコモメールバックアップアプリを公開しました

昨日公開しました。
現在は最小の機能にて実装されています。

なお、spモードメールバックアップをご利用の方は、優待ライセンスで購入することができます。

方法はspモードメールバックアップを最新版へアップデート。一度spモードメールバックアップを起動

これで、ドコモメールバックアップアプリから、タスク追加を押すと、優待ライセンスになるはずです。

ドコモメールバックアップのコミュニティを作成しました

SPモードメールバックアップに代わるドコモメールバックアップ用のコミュニティを公開しました
Android4.0以上の端末が対象となります。
数週間のうちにファーストリリースを行う予定です。

ドコモメールの方のみご利用いただけます。

以前のようにEML出力などは介さず、基本全自動でタスク実行できるようになります。

またコミュニティを中心に随時情報を公開していきます。

Google+

Quick電話帳Ver8.2.1を公開しました

CloudSaveにおける不具合を修正しました

SONYのレンズカメラQX100がWIFI接続できなくなった場合の解消法

私の端末で初めてなったので解消方法を。。。

具体的にはwifiアクセスポイントとしてPlayMemoriesでQX100には接続できる(というメッセージは表示される)のですが、その後いくら時間がたっても
画面にカメラ側の映像が表示されない。

Android端末側の再起動でも解消せず
QX100の電源ON,OFFでも解消しませんでした。

QX100はNFC待機状態で待機するため、おそらくですが電源OFFをしても通電はしたまんまだと思われます。
要は電源OFFはスリープのようなもので明示的にはOFFになっていないと。

ということでバッテリーの取り外しをして、完全に再起動するとつながりました。

レンズカメラがおかしくなってつながらない~みたいなのをたまにレビュー欄で見かけるのですが
一度お試しください。

環境
 Nexus5 4.2.2
 Sony QX-100
 PlayMemories 4.0.1

KitKat:4.4でimage選択intentを利用する

はじめに




このエントリは Android Advent Calendar 2013 の9日目(12/9)の記事になります。

KitKatで搭載されたStorage Access Frameworkを使ったアプリからの画像選択の取り扱い方法
全然記事みつけられなくてて苦労したので少しでも参考になればとおもって書きます。


本題



さてAndroid4.4からStorage Access Framework(SAF)が導入されましたね
私が作っているアプリでもintentを発行して画像を選択するアプリを作っていたのですが

1.画像を選択
2.com.android.camera.action.CROPでクロップ処理のIntentを発行
3.投げた先のアプリでで強制終了してしまうという結末に

最初はギャラリーとかアルバムアプリを疑いました。(遷移先アプリで強制終了したので)

でもギャラリーとかがおかしいとかないよねとおもって調べたのですが
Intentの呼び出しとResultは以下のようなコードで書いていました
protected void showPickerIntent(){
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, PICKER_INTENT);
}
こんな感じでintentが発行されて画面が表示されます
Screenshot_2013-12-03-21-16-03

この時点でお分かりだと思いますが4.3以前の場合ですとギャラリー・アルバムなどの写真選択ができるアプリしか
Intentの対象になっていませんでしたが4.4ですと状況が一変しています。
DropboxやESファイルエクスプローラなどのファイルが扱えたりするもの、はたまたGoogleDriveまで選択できます。
(SAFのプロバイダを提供しているアプリがでているんですかね)

さて選択画面で画像を選択してonActivityResultで戻り値を受け取ります。
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
     case PICKER_INTENT:
         if (resultCode == Activity.RESULT_OK){
             if(data == null || data.getData() == null) {
                return;
             }
         Toast.makeText(context,data.getData().toString(),Toast.LENGTH_SHORT).show();
     }
  }
}

Toastで中身を見てみます。
アルバムやギャラリーなどの写真表示系のアプリから写真を選択した場合は
getData()の中身はcontent://media/external/images/media/XXXXのような形式でURLが返却されます。
この場合はCROPへ処理を投げても強制終了はしませんでした(4.3系と同じですね)

ただしほかのアプリを選択した場合違うURLが返却されます。

私が確認した限りでは、
Dropbox
file:///storage/emulated/0/Android/data/com.dropbox.android/files/scratch/35_1_20120927183120.jpg
GoogleDrive
content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3D204

このようなURLで返却されておりそのままCROPへIntent発行してしまうと対応しているURLじゃないので落ちてしまいます。
これで私のアプリが投げているパラメータが悪いということがわかりました。
 
 

どうやってDropboxやGoogleDriveのイメージに対応するか



実はDropBox(file://の場合)はDropboxで画像を選択した時点でDropboxアプリがサーバからデータを取得してくれるので単純にファイルとして扱えば問題なくCROPまでIntentを投げることができました。

問題はGoogleDriveです。

さっぱり記事が見つからず(見つけられず)いろいろ試行錯誤したのですが
content://から始まるのでContentResolverを利用したら取れるのかなと思ったら取れました。
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
       switch (requestCode) {
            case PICKER_INTENT:
                if (resultCode == Activity.RESULT_OK){
                    if(data == null || data.getData() == null) {
                       Cursor cursor = getActivity().getContentResolver().query(uri,null, null, null, null);
                       cursor.moveToFirst();
                       int docIdIndex = cursor.getColumnIndex("document_id") ;
                       String fpath = cursor.getString(docIdIndex);
                       int index = cursor.getColumnIndex("mime_type");
                       String type = cursor.getString(index);
                       //TypeがImageのものだけ処理
                       if(type != null && type.contains("image")){
                       //GDrive処理
                       downloadPicker(data.getData());
                       return;
                    }
                }
            }
        }
}

public void downloadPicker(Uri uri){
       //非同期処理呼び出し
       new DownloadSAFFile(this.getActivity(),uri).execute();
}

public class DownloadSAFFile extends AsyncTask<Void,Void,File>{
      private Context context;
      private Uri uri;

      public DownloadSAFFile(Context context,Uri uri){
         this.context = context;
         this.uri = uri;
      }
      @Override
      protected File doInBackground(Void... params)
      {
            File cacheFile=new File(context.getExternalCacheDir(), "image_cache");
            try {
                        InputStream is = null;
                        //ここで取り出し
                        is = context.getContentResolver().openInputStream(uri);
                        OutputStream os = new FileOutputStream(cacheFile);
                        FileUtility.copyStream(is, os);
                        return cacheFile;
            } catch (Exception ex) {
                  // something went wrong
                  ex.printStackTrace();
                  return null;
            }
      }

      @Override
      protected void onPreExecute()
      {
      }

      @Override
      protected void onPostExecute(File file)
      {
            if(file != null){
            //file処理する
            //パラメータのファイルが実態なのであとはこのfileを扱えばOK
            }else{
                  Toast.makeText(context,"error", Toast.LENGTH_SHORT).show();
            }
      }
}
なぜ非同期なのかとなるのですがやはり外部へのアクセスになるのでデータのサイズやネットワーク状況によってダウンロードが遅い場合固まってしまうようにユーザから見えてしまうのでバックグラウンドで処理する必要があります。(あまり確認していないのですが長時間かかるとANRになるかも。また処理前と処理あとでダイアログなりなんなり上げてください)

これでGoogleDriveのデータもPickerで呼び出しできます。
 
 

残った課題



実は実装した際にダウンロード中にダイアログを上げるようにしたのですが、GoogleDrive上にあるものは
良いのですが、GoogleDriveからすでにダウンロードしてローカルにあるものについて実行すると
ダイアログが一瞬出て、すぐ閉じる(もちろんローカルにあるので)こととなってしまいました。
いろいろとコンテンツのUriのパラメータからダウンロード済みかどうか判断できるかどうかも調べたのですが
結果としてできませんでした。もしご存じの方いれば教えてください!
 
 

最後に



Storage Access Frameworkを利用すれば今まで簡単には使えなかったGoogleDriveへのファイルアクセスが簡単にできます。
ぜひぜひみなさんStorage Access Framework有効に使いましょう!

Quick電話帳/Ver8.1を公開しました

KitKatのStorageAccessFrameworkへの対応
フォントの追加
マニュアル画面の変更
その他バグフィックス

などです。

Quick電話帳/Ver8.0.0を公開しました

Android4.4 KitKatへの対応
高解像度端末(Nexus5など)への一部アイコンを更新
スタイル・テーマの見直し