アプリ内のファイルをSDカードに保存する方法について

3,710 views
Skip to first unread message

Greg

unread,
Dec 9, 2012, 10:25:48 PM12/9/12
to android-g...@googlegroups.com
いつもお世話になっております。
Gregと申します。


アプリ内のファイルをSDカードに保存する方法について
質問させて下さい。

【やりたいこと】
アプリ内(/res/drawable)に配置したファイル(PNGやPDF)を
SDカード内に保存したい。

FileChannelクラスというものがあると知り、
以下のように使用してみました。

------------------------------------------------------------------------
・・・

File inFile = new File("android.resource://" + getPackageName() + "/" + R.drawable.xxxxxx);  //「xxxxxx」は/res/drawableに配置したファイル名
File outFile = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "testname.png");
try {
FileChannel inChannel = new FileInputStream(inFile).getChannel();
FileChannel outChannel = new FileOutputStream(outFile).getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
outChannel.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

・・・
------------------------------------------------------------------------

この場合LogCatのエラーメッセージには
: java.io.FileNotFoundException: /android.resource:/パッケージ名/2130837506: open failed: ENOENT (No such file or directory)
と出てしまいます。

パスの指定を直接指定して
File inFile = new File("android.resource://" + getPackageName() + "/res/drawable/xxxxxx.png");
としても同様の結果でした。

対象のフォルダにはたしかに配置してあるのに、
上記のようなエラーが出る原因がわかりませんでした。


またFileOutputStreamを使う方法も試してみました。
こちらは例外処理は抜けてエラーは出ないのですが、
ファイルがコピーされませんでした。

------------------------------------------------------------------------
・・・

File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "testname.png");
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.xxxxxx);
try {
OutputStream stream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

・・・
------------------------------------------------------------------------


以上のようにアプリ内のファイルをSDカードに保存することが
実現できていない状況です。

エラー原因、対処の方法について
ご教授頂けないでしょうか。

またより良い方法があれば、教えて頂けないでしょうか。
よろしくお願いします。

Hirokazu Fukami

unread,
Dec 9, 2012, 10:34:53 PM12/9/12
to android-g...@googlegroups.com
こんにちはfkmです。

/res/drawable内の画像ファイル(PNG)であれば、
一度Bitmapにして、Bitmap.compress()メソッドで書き出すという手が使えます。

2012/12/10 Greg <miura.y...@gmail.com>:
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このディスカッションをウェブ上で閲覧するには、https://groups.google.com/d/msg/android-group-japan/-/sz1xddhUjAQJ
> にアクセスしてください。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> このグループから退会するには、android-group-j...@googlegroups.com
> にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja
> からこのグループにアクセスしてください。



--
-------------------------------------------------------------
深見 浩和(Hirokazu Fukami)

URI:http://www.fkmsoft.jp
email: f...@fkmsoft.jp

noxi

unread,
Dec 9, 2012, 10:35:20 PM12/9/12
to android-g...@googlegroups.com
noxiです。

こういうやり方は初めて見ました。斬新でびっくりです。
どこかに「これでリソースを読める」と書いてあったのでしょうか?

リファレンス引いただけで使ったことは無いので確証はありませんが、
Resources#openRawResourceを使えば出来そうな気もします。

InputStream in = getResources().openRawResource(R.drawable.ic_launcher);
OutputStream out = new FileOutputStream(...);
IOUtils.copy(in, out);

※apache commons IO のIOUtils

リソースとして扱わないでも良いのであれば、assetsに入れた方が良いと思います。


2012年12月10日 12:25 Greg <miura.y...@gmail.com>:

noxi

unread,
Dec 9, 2012, 11:09:04 PM12/9/12
to android-g...@googlegroups.com
noxiです。補足です。

Java仕様として、Fileクラスで扱えるモノは「file://」スキーマだけで
「android.resouce://」は利用できないと認識しています。

なので試しておられる方法は利用できません。


2012年12月10日 12:35 noxi <android.w...@gmail.com>:

Greg

unread,
Dec 10, 2012, 10:43:21 PM12/10/12
to android-g...@googlegroups.com
>fkm様

2つ目のソースがBitmap.compress()メソッドを使用したものだったのですが、
使い方が間違っているでしょうか。

>noxi様

開発を始めて間もなく知識も乏しいので、
見当違いの使い方だったでしょうか。申し訳ありません。

Apache Commonsについての情報、ありがとうございます。
Eclipse環境への導入方法と合わせて調べてみます。

またassetsフォルダには1M以上のファイルは配置できない、
ということを耳にしたので、resフォルダに配置することを考えておりました。
あまり容量が大きいようなら、ダウンロードさせる方法を使用した方が良いのかもしれませんが。



2012年12月10日月曜日 12時25分48秒 UTC+9 Greg:

MORIHIRO

unread,
Dec 10, 2012, 11:03:51 PM12/10/12
to android-g...@googlegroups.com
まずは android.permission.WRITE_EXTERNAL_STORAGE が抜けてないかが
気になるところですが、以下のリファレンス中のサンプルコード
  createExternalStoragePublicPicture()
が参考になるんじゃないでしょうか。

http://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory%28java.lang.String%29

2012年12月11日火曜日 12時43分21秒 UTC+9 Greg:

たろサ

unread,
Dec 10, 2012, 11:14:14 PM12/10/12
to android-g...@googlegroups.com
 たろサです。

try {
  FileOutputStream stream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, stream);
stream.flush();
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

 これでダメですか?
 あとは下記を書いているかどうか。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このディスカッションをウェブ上で閲覧するには、https://groups.google.com/d/msg/android-group-japan/-
> /sz1xddhUjAQJ にアクセスしてください。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してく
> ださい。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセス
> してください。

--
山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----
E-Mail: taro...@gmail.com

noxi

unread,
Dec 10, 2012, 11:20:13 PM12/10/12
to android-g...@googlegroups.com
noxiです。

commons IOを使ったのはただその辺の処理を省略するのに便利だからで、
深い意味は無いのであまり気にしないでください。

assetsへ1MB以上のファイルを含めたい場合、分割すれば良いと思います。
これが参考になるはずです。


また最初のエラーが
 java.io.FileNotFoundException: /android.resource:/パッケージ名/2130837506: open failed: ENOENT (No such file or directory)
であり、出力側をどう頑張ったところでそもそもの原因が
リソースをファイルとして取得することが失敗しているところに有り、
そこが解消されない限りはあまり意味を持たないと思います。


2012年12月11日 13:14 たろサ <taro...@gmail.com>:
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。

たろサ

unread,
Dec 10, 2012, 11:36:05 PM12/10/12
to android-g...@googlegroups.com
 たろサです。

 こんにちは。

> リソースをファイルとして取得することが失敗しているところに有り、
> そこが解消されない限りはあまり意味を持たないと思います。

 Gregさんの最初のメールに、
> File file = new File(Environment.getExternalStoragePublicDirectory(
> Environment.DIRECTORY_DOWNLOADS), "testname.png");
> Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.xxxxxx);
> try {
> OutputStream stream = new FileOutputStream(file);
> bitmap.compress(CompressFormat.PNG, 100, stream);
> stream.close();
> } catch (FileNotFoundException e) {
> e.printStackTrace();
> } catch (IOException e) {
> e.printStackTrace();
> }

 こう書いてあったので、bitmapの取得はできているものと思っていました。
 ただ、FileOutputStreamでなく、OutputStream と書いているのが気になったのと、とりあえず、flush()も入
れとこうと思って、メールした次第です。

 Gregさん頑張ってください。

(2012/12/11 13:20), noxi wrote:
> noxiです。
>
> commons IOを使ったのはただその辺の処理を省略するのに便利だからで、
> 深い意味は無いのであまり気にしないでください。
>
> assetsへ1MB以上のファイルを含めたい場合、分割すれば良いと思います。
> これが参考になるはずです。
> http://d.hatena.ne.jp/itog/20091228/1262016898
>
>
> また最初のエラーが
> > java.io.FileNotFoundException: /android.resource:/パッケージ名/2130837506: open failed: ENOENT
> (No such file or directory)
> であり、出力側をどう頑張ったところでそもそもの原因が
> リソースをファイルとして取得することが失敗しているところに有り、
> そこが解消されない限りはあまり意味を持たないと思います。
>
>
> 2012年12月11日 13:14 たろサ <taro...@gmail.com <mailto:taro...@gmail.com>>:
> <mailto:android-g...@googlegroups.com> にメールを送信してください。
> > このグループから退会するには、android-group-j...@googlegroups.com
> <mailto:android-group-japan%2Bunsu...@googlegroups.com> にメールを送信してく
> > ださい。
> > 詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにア
> クセス
> > してください。
>
> --
> 山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----
> E-Mail: taro...@gmail.com <mailto:taro...@gmail.com>
>
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループに投稿するには、android-g...@googlegroups.com
> <mailto:android-g...@googlegroups.com> にメールを送信してください。
> このグループから退会するには、android-group-j...@googlegroups.com
> <mailto:android-group-japan%2Bunsu...@googlegroups.com> にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアク
> セスしてください。
>
>
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。

Greg

unread,
Dec 11, 2012, 10:19:24 AM12/11/12
to android-g...@googlegroups.com
>MORIHIRO様

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>は
ManiFestファイルに記述しております。
ディレクトリ作成方法等、教えて頂いたリンクは参考にさせて頂きます。

>noxi様

1番目の方法ではファイル自体読み込めてないので、
ご指摘頂いた通り、ファイルパスの取得方法が誤ってるのが原因のようです。
assetsへのファイル分割による配置も検討させて頂きます。

>たろさ様

教えて頂いた方法でファイルコピーできました。
また2番目の方法でも、ファイルコピーはできておりました。
申し訳ありません。
ファイル制御を考えるとFileOutputStreamの方が適切のようですね。
flushメソッドですが、リファレンスを参照する限り
バッファの出力を保証するものでしょうか。


取り敢えずはPNG、PDFファイルともにコピーすることができした。
アドバイスをして頂きました皆様、ありがとうございました。

2012年12月10日月曜日 12時25分48秒 UTC+9 Greg:

Greg

unread,
Dec 11, 2012, 10:21:49 AM12/11/12
to android-g...@googlegroups.com
追加で申し訳ありませんが、質問させて頂きたいことがあります。

DownloadManagerクラスを用いて画像ファイルをダウンロードした際、
Android標準のギャラリーで画像ファイルが保存されていることが確認できました。
しかし、上記のようにアプリ内のファイルをコピーして保存した場合、
Android標準のギャラリーでは確認できず、ファイルマネージャだと確認することができました。
Android端末に保存された画像等については、
すべてギャラリーで確認できものると勘違いしておりました。

保存先はどちらも下記のように、
------------------------------------------------------------------------
 File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "testname.png");
------------------------------------------------------------------------
同じ方法で指定したのに、このような違いがでる原因は何故でしょうか。


よろしければご教授願います。




Koutarou Tanaka

unread,
Dec 11, 2012, 1:28:06 PM12/11/12
to android-g...@googlegroups.com
たなかと申します。

MediaScannerConnectionとかその辺りで調べてみると良いと思います。

-- 
Koutarou Tanaka
Sparrow を使って送信

日付:2012年12月12日水曜日、時刻:0:21、差出人:Greg:

--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このディスカッションをウェブ上で閲覧するには、https://groups.google.com/d/msg/android-group-japan/-/rjTNrQU-LikJ にアクセスしてください。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。

Greg

unread,
Dec 13, 2012, 5:46:46 PM12/13/12
to android-g...@googlegroups.com
>たなか様

ありがとうございます。
参考にさせて頂きます。
Reply all
Reply to author
Forward
0 new messages