素人のアンドロイドアプリ開発日記

ファイル操作のコンテンツ

保存した内容を本体に認識をさせる。

2011.04.15

お絵かきアプリで書いた絵を保存する。で生成した画像のファイルですが、ファイル管理ツールなどで、保存が確認できるのですが、ギャラリーなどで、表示がされない。一度再起動などすると、確認が出来る。と言った現象が起こります。

今回はこの保存の問題に関して解決をしたいと思います。

アプリから撮影した写真画像が、ギャラリーから見れない

では、

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()));

上記でメディアスキャンを呼び出してくれるようです。(すいません、この方法は未確認です。)

Broadcast Intent 一覧

問題点:これだとメディアスキャンを全体に実行をするので、時間がかかるようです。

 

アプリから撮影した写真画像が、ギャラリーから見れない

ContentValues values = new ContentValues();
ContentResolver contentResolver = getContentResolver();
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(Images.Media.LATITUDE, loc.getLatitude());
values.put(Images.Media.LONGITUDE, loc.getLongitude());
values.put(Images.Media.TITLE, fileName);  // タイトル名(ファイル名にしてます)
values.put("_data", filePath); // 画像の保存されたフルパス
contentResolver.insert(Media.EXTERNAL_CONTENT_URI, values);

僕の作った方では【Media.EXTERNAL_CONTENT_URI】が正確に動作をしてくれなくて【MediaStore.Images.Media.EXTERNAL_CONTENT_URI】だと正確に認識してくれました。

参照:http://labs.techfirm.co.jp/android/cho/2118

この方法は、使っているfunctionの推定なんですが、アンドロイドアプリの画像管理などのデータベースに直接書き込んでいるような印象です。

でここまででかなりまとまっては来たのですが、上書きをした場合に、そのギャラリーなどの表示が更新されない。という、問題にぶち当たります。

insertだけでなく、contentResolver.delete,contentResolver.updateなどの関数を用いても更新はされません。

上書き処理を行うには、次の方法で現在のデータを一度消してから、insertをする必要があります。

画像更新処理に関して

File saveFile = new File(path);
if(saveFile.exists()) {
 String[] proj = {MediaStore.Images.Media._ID,MediaStore.Images.Media.DATA};
 Cursor cursor = activity.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,proj,MediaStore.Images.Media.DATA + " = ?",new String[] { path },null);
 if(cursor.getCount() != 0) {
 cursor.moveToFirst();
 Uri deleteUri = ContentUris.appendId(
 MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon(),
 cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID))).build();
 activity.getContentResolver().delete(delete, null, null);
 }
}

以上で上書きの処理ができました。

ですが、ユーザーがこのアプリで上書きをする必要性がなければ、同じ名前を回避してあげる(アラートで他の名前に変えさせる・ランダムな名前)で解決をした方がよいような気がします。

カテゴリー:ファイル操作

画像をスライドショーとして表示する。完成:ファイル一式。

2011.03.30

画像をギャラリー形式での表示を行います。

何度か、「画像をスライドショーとして表示をする。」として、行ってきました。

画像をスライドショーとして表示する。SDカードの認識

画像をスライドショーとして表示する。画像のファイルにアクセス

画像をスライドショーとして表示する。画像のファイルを読み込む

画像をスライドショーとして表示する。BaseAdapterでAdapterを作る。

下記の形でスライドショーを完成できました!

 

ゼロからのAndroidアプリケーション開発入門

を参考に改良したものを作成させていただいております。

 

レイアウトとしては、下記のような、形で、上にサムネイル。下に表示領域を用意する。

gallery

 

最初にmain.xmlは下記のような形になります。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 >
 <Gallery 
 android:layout_height="wrap_content" 
 android:id="@+id/gallery1" 
 android:layout_width="fill_parent"></Gallery>
 <ImageView 
 android:layout_height="fill_parent" 
 android:src="@drawable/icon" 
 android:id="@+id/imageView1" 
 android:layout_width="fill_parent"></ImageView>
</LinearLayout>

レイアウトはlinearLayoutを用いて、Galleryは高さがwrap_contentで、ImageViewの方はfill_parentとして、イメージの部分を使いやすいようにしておく。

SlideGallery.javaは下記のようになる。

package in.andante.slide;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemClickListener;

public class SlideGallery extends Activity implements DialogInterface.OnClickListener,OnItemClickListener,Runnable{
 /** Called when the activity is first created. */

 private ProgressDialog dialog;
 private ImageView imageView;
 private Gallery gallery;
 private Bitmap[] thumbnail;
 private List<String> dirList = new ArrayList<String>();
 private List<String> tmp = new ArrayList<String>();
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);

 if(!sdcardReadReady()){
 new AlertDialog.Builder(this)
 .setMessage("SDカードにアクセスできません。")
 .setNeutralButton("OK", this)
 .show();
 return;
 }
 dirList.add(Environment.getExternalStorageDirectory().getPath());
 int i = 0;
 int j = 0;
 while(dirList.size() > i){  
 File subDir = new File(dirList.get(i));  
 String subFileName[] = subDir.list();
 j = 0;
 if(subFileName != null){
 while(subFileName.length > j){  
 File subFile = new File(subDir.getPath() + "/" + subFileName[j]);  
 if(subFile.isDirectory()){
 String _st =subDir.getPath() + "/" + subFileName[j]; 
 dirList.add(_st);
 }else if(subFile.getName().endsWith("jpg") || subFile.getName().endsWith("JPG")){  
 tmp.add(subDir.getPath() + "/" + subFileName[j]);  
 }  
 j++;
 }
 }
 i++;  
 }

 if(tmp.isEmpty()){
 new AlertDialog.Builder(this)
 .setMessage("画像のデータがありません")
 .setNeutralButton("OK", this)
 .show();
 return;
 }

 //tmp.toArray();
 dialog = new ProgressDialog(this);
 dialog.setMessage("読み込みを行います。");
 dialog.show();
 thumbnail = new Bitmap[tmp.size()];
 new Thread(this).start();
 gallery = (Gallery)findViewById(R.id.gallery1);
 gallery.setSpacing(8);
 gallery.setAdapter(new GalleryAdapter());
 gallery.setOnItemClickListener(this);
 imageView = (ImageView)findViewById(R.id.imageView1);
 Bitmap picture = BitmapFactory.decodeFile(tmp.get(0));
 imageView.setImageBitmap(picture);
 }

 public void run(){
 for(int i = 0 ; i < tmp.size(); i++){
 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeFile(tmp.get(i),options);
 int height = options.outHeight;
 int scale = height /50;
 options.inSampleSize = scale;
 options.inJustDecodeBounds = false;
 thumbnail[i] = BitmapFactory.decodeFile(tmp.get(i),options);
 }
 dialog.dismiss();
 }

 private boolean sdcardReadReady(){
 String state = Environment.getExternalStorageState();
 return (Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state));
 }

 @Override
 public void onClick(DialogInterface dialog, int which) {
 switch(which){
 case DialogInterface.BUTTON_NEUTRAL:
 dialog.dismiss();
 finish();
 }
 }

 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
 // TODO Auto-generated method stub
 if(arg0 == gallery){
 Bitmap picture = BitmapFactory.decodeFile(
 tmp.get(arg2)    
 );
 imageView.setImageBitmap(picture);
 }
 }
 public class GalleryAdapter extends BaseAdapter{

 @Override
 public int getCount() {
 // TODO Auto-generated method stub
 return tmp.size();
 }

 @Override
 public Object getItem(int position) {
 // TODO Auto-generated method stub
 return null;
 }

 @Override
 public long getItemId(int position) {
 // TODO Auto-generated method stub
 return 0;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 // TODO Auto-generated method stub
 ImageView view;
 if(convertView == null){
 view = new ImageView(SlideGallery.this);
 view.setImageBitmap(thumbnail[position]);
 }else{
 view = (ImageView)convertView;
 }
 return view;
 }
 }
}

以上で簡単にではありますが、SDcardの中のスライドショーが完成しました。

カテゴリー:ファイル操作

画像をスライドショーとして表示する。BaseAdapterでAdapterを作る。

2011.03.29

スライドショーを作成する時に、画像を選ぶ部分を作成します。

その時、画像の配列を用意する事で、画像のサムネイルを用意する事ができます。

main.xmlでGalleryと言う項目があるので、配置をしておいてください。

クラスを作成する際にはBaseAdapterを利用します。

public class galleryAdapter extends BaseAdapter{};

このBaseAdapterを継承する事で次のファンクションを作成する必要があります。

public class galleryAdapter extends BaseAdapter{
 
  @Override
  public int getCount() {
    // TODO Auto-generated method stub
    return ((int)ギャラリーの数);
  }

  @Override
  public Object getItem(int position) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public long getItemId(int position) {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    ImageView view;
    if(convertView == null){
      view = new ImageView((Activityで使用しているクラス).this);
      view.setImageBitmap(画像の配列[position]);
    }else{
      view = (ImageView)convertView;
    }
    return view;
  }
}

上記の式を書く。この値に関してGalleryに付加をsetAdapterを用いて行う。

gallery.setAdapter(new galleryAdapter());

で付加をする。コンストラクタ自体は記入してはいないが、getCountで指定した数の長さだけ、getViewで作成をしたファイルでギャラリーを作成してくれる。

カテゴリー:ファイル操作

画像をスライドショーとして表示する。画像のファイルを読み込む

2011.03.29

画像のファイルをアプリ内に読み込む時には、BitmapFactoryクラスを利用する。

この時、BitmapFactoryのOptionsを用いて、読み込む画像に対しての制限などが行える。画像サイズなどそのサイズのまま読み込むと大きなメモリを使ってしまう事がある為、画像に関しては一定のサイズに変更をして読み込むなどの処理が求められる。

1、***.jpgのサイズだけを読み込む

BitmapFactoryのOptionsにはinJustDecodeBoundsと言う変数を持っている。この値をtrueとすると、画像は読み込まず、画像のサイズなどの情報を先に読み込む事ができる。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile("***.jpg",options);

上記のかたちで、optionsの中に画像の幅のデータなどが含まれるので、画像のデータを元に縮小率を設定する。縮小率に関しては、inSampleSizeで設定ができる。(縮小率を利用する。※拡大率ではない。)縦の大きさを50に固定をして表示をする事が下記でできる。

int _imgHeight = options.outHeight;
int _imgScale = _imgHeight/50;
options.inSampleSize = scale

また画像を取得する時は、先ほどのinJustDecodeBoundsをfalseに変更する必要があるので

options.inJustDecodeBounds = false;
Bitmap picture = BitmapFactory.decodeFile("***.jpg",options

でpictureの中に画像のデータをbitmapで入れる事ができた。

つづく

カテゴリー:ファイル操作

画像をスライドショーとして表示する。画像のファイルにアクセス

2011.03.29

前回はSDcardへのアクセスを行いました

今回はSDcardの中から画像のファイルのみを対象としてアクセスをしてみたいと思います。

sdcardのパスは次のように取得できます。

String sdcardDir = Environment.getExternalStorageDirectory().getPath();

ディレクトリのみのリストを作成してその中にこのディレクトリを入れます。

dirList.add(sdcardDir);

この時点でdirListに関しては、sdcardのフォルダだけで問題ありません。

このdirListに関しては「写真のファイルがあれば、imgListに追加」ディレクトリが存在すれば、dirListに追加

といった形で配置を行う。(参照:Android Techfirm Lab

int i = 0;  
int j = 0;  
while(dirList.size() > i){  
 File subDir = new File(dirList.get(i));  
 String subFileName[] = subDir.list();  
 j = 0;  
 while(subFileName.length > j){  
   File subFile = new File(subDir.getPath() + "/" + subFileName[j]);  
   if(subFile.isDirectory()){  
     dirList.add(subDir.getPath() + "/" + subFileName[j]);  
   }else if(subFile.getName().endsWith("jpg") 
     || subFile.getName().endsWith("JPG")){  
     imgList.add(subDir.getPath() + "/" + subFileName[j]);  
   }  
   j++;  
 }  
 i++;  
}

これでimgListの中にsdcard内の画像のパスを入れる事ができました。一通り読み込みができました。listのsize()とarrayのlengthが似ているなーと思います。中身の数を返してくれます。その他の部分に関してはパスをrootからで取得を行う事で、パスを取得できました。

カテゴリー:ファイル操作

公開中のアプリ、是非ダウンロードしてみてください

2chまとめのたね

RSSを利用してさまざまなブログの情報をキュレーションしてくれるアプリ

インストールする

ひらがな戦記

OPENGL ES2 を利用したカルタのソーシャルゲーム

インストールする