よくあるサンプルは assets や raw にある Gif を読むやつばっかりです。
- InputStream is = context.getResources().openRawResource(R.drawable.piggy);
- Movie movie = Movie.decodeStream(is);
とか
- InputStream is = context.getAssets().open("piggy.gif");
- Movie movie = Movie.decodeStream(is);
SD にある Gif ファイルから読もうとして
- try {
- InputStream is = new FileInputStream(filePath);
- Movie movie = Movie.decodeStream(is);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
LogCat で
09-19 15:38:37.828: W/System.err(7523): java.io.IOException 09-19 15:38:37.828: W/System.err(7523): at java.io.InputStream.reset(InputStream.java:218) 09-19 15:38:37.828: W/System.err(7523): at android.graphics.Movie.decodeStream(Native Method)
と出ていて、どうも InputStream の reset() で起こっていると。
InputStream のコードをみると、サブクラスが Override しないかぎり IOException が投げられるようになっています。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/libcore/luni/src/main/java/java/io/InputStream.java#217
- 217 public synchronized void reset() throws IOException {
- 218 throw new IOException();
- 219 }
FileInputStream は Override してませんでした。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/libcore/luni/src/main/java/java/io/FileInputStream.java
AssetManager の open() で返ってくる InputStream は AssetInputStream です。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/content/res/AssetManager.java#288
- 288 public final InputStream open(String fileName) throws IOException {
- 289 return open(fileName, ACCESS_STREAMING);
- 290 }
- 309 public final InputStream open(String fileName, int accessMode)
- 310 throws IOException {
- 311 synchronized (this) {
- 312 if (!mOpen) {
- 313 throw new RuntimeException("Assetmanager has been closed");
- 314 }
- 315 int asset = openAsset(fileName, accessMode);
- 316 if (asset != 0) {
- 317 AssetInputStream res = new AssetInputStream(asset);
- 318 incRefsLocked(res.hashCode());
- 319 return res;
- 320 }
- 321 }
- 322 throw new FileNotFoundException("Asset file: " + fileName);
- 323 }
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/content/res/AssetManager.java#538
- 538 public final class AssetInputStream extends InputStream {
- 569 public final void reset() throws IOException {
- 570 seekAsset(mAsset, mMarkPos, -1);
- 571 }
- 597 }
InputStream のサブクラスで reset() を継承しているクラスとして BufferedInputStream があります。
このクラスを使って、次のようにすると IOException が発生せずに読むことができます。
- try {
- InputStream stream = new BufferedInputStream(
- new FileInputStream(filePath), 16 * 1024);
- stream.mark(16 * 1024);
- mMovie = Movie.decodeStream(stream);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
ちなみに Movie には deocdeFile() というメソッドもあるのですが、なかみは FileInputStream 使ってるだけなので、使えません。。。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/graphics/java/android/graphics/Movie.java#51
- 51 public static Movie decodeFile(String pathName) {
- 52 InputStream is;
- 53 try {
- 54 is = new FileInputStream(pathName);
- 55 }
- 56 catch (java.io.FileNotFoundException e) {
- 57 return null;
- 58 }
- 59 return decodeTempStream(is);
- 60 }
おまけ
Movie.cpp
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/jni/android/graphics/Movie.cpp#82
- 82 static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
- 83
- 84 NPE_CHECK_RETURN_ZERO(env, istream);
- 85
- 86 // what is the lifetime of the array? Can the skstream hold onto it?
- 87 jbyteArray byteArray = env->NewByteArray(16*1024);
- 88 SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
- 89 if (NULL == strm) {
- 90 return 0;
- 91 }
- 92
- 93 SkMovie* moov = SkMovie::DecodeStream(strm);
- 94 strm->unref();
- 95 return create_jmovie(env, moov);
- 96 }
- 12 class JavaInputStreamAdaptor : public SkStream {
- 13 public:
- 14 JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar)
- 15 : fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) {
- 16 SkASSERT(ar);
- 17 fCapacity = env->GetArrayLength(ar);
- 18 SkASSERT(fCapacity > 0);
- 19 fBytesRead = 0;
- 20 }
- 21
- 22 virtual bool rewind() {
- 23 JNIEnv* env = fEnv;
- 24
- 25 fBytesRead = 0;
- 26
- 27 env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID);
- 28 if (env->ExceptionCheck()) {
- 29 env->ExceptionDescribe();
- 30 env->ExceptionClear();
- 31 SkDebugf("------- reset threw an exception\n");
- 32 return false;
- 33 }
- 34 return true;
- 35 }
- ...
- 145 SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- 146 jbyteArray storage, int markSize) {
- 147 static bool gInited;
- 148
- 149 if (!gInited) {
- 150 jclass inputStream_Clazz = env->FindClass("java/io/InputStream");
- 151 RETURN_NULL_IF_NULL(inputStream_Clazz);
- 152
- 153 gInputStream_resetMethodID = env->GetMethodID(inputStream_Clazz,
- 154 "reset", "()V");
- 155 gInputStream_markMethodID = env->GetMethodID(inputStream_Clazz,
- 156 "mark", "(I)V");
- 157 gInputStream_availableMethodID = env->GetMethodID(inputStream_Clazz,
- 158 "available", "()I");
- 159 gInputStream_readMethodID = env->GetMethodID(inputStream_Clazz,
- 160 "read", "([BII)I");
- 161 gInputStream_skipMethodID = env->GetMethodID(inputStream_Clazz,
- 162 "skip", "(J)J");
- 163
- 164 RETURN_NULL_IF_NULL(gInputStream_resetMethodID);
- 165 RETURN_NULL_IF_NULL(gInputStream_markMethodID);
- 166 RETURN_NULL_IF_NULL(gInputStream_availableMethodID);
- 167 RETURN_NULL_IF_NULL(gInputStream_availableMethodID);
- 168 RETURN_NULL_IF_NULL(gInputStream_skipMethodID);
- 169
- 170 gInited = true;
- 171 }
- 172
- 173 if (markSize) {
- 174 env->CallVoidMethod(stream, gInputStream_markMethodID, markSize);
- 175 }
- 176
- 177 return new JavaInputStreamAdaptor(env, stream, storage);
- 178 }
0 件のコメント:
コメントを投稿