Hotfix for the html5 video bug

This should be a temporary solution until we can find a better way to
fix this.
Since the `ParcelFileDescriptor` pipe always breaks when writing a video,
I've fixed the issue by just writing the video to the local file system
and then returning that local file to the ContentProvider.
This local file gets deleted when the App gets destroyed.
This commit is contained in:
Rashiq 2015-05-11 21:58:09 +02:00
parent 6f0516f61a
commit b51db12b11
4 changed files with 104 additions and 31 deletions

View File

@ -14,7 +14,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-sdk
@ -23,7 +23,8 @@
<application
android:icon="@drawable/kiwix_icon"
android:label="@string/app_name"
android:allowBackup="true">
android:allowBackup="true"
android:hardwareAccelerated="true">
<activity
android:name=".KiwixMobileActivity"
android:label="@string/app_name"
@ -38,6 +39,7 @@
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="file"/>
<data android:pathPattern=".*\\.zim(aa|)"/>
<data android:pathPattern=".*\\..*\\.zim(aa|)"/>
@ -47,8 +49,10 @@
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.zim(aa|)"/>
@ -59,8 +63,10 @@
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.zim(aa|)"/>
@ -71,8 +77,10 @@
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="content"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.zim(aa|)"/>
@ -86,8 +94,9 @@
android:name=".settings.KiwixSettingsActivityGB"
android:theme="@style/AppStyle"/>
<activity android:name=".settings.KiwixSettingsActivityHC"/>
<activity android:name=".LibraryActivity"
android:theme="@style/AppStyle"/>
<activity
android:name=".LibraryActivity"
android:theme="@style/AppStyle"/>
<provider
android:name=".ZimContentProvider"

View File

@ -0,0 +1,28 @@
package org.kiwix.kiwixmobile;
import android.content.Context;
import android.os.Environment;
import java.io.File;
public class FileUtils {
public static File getFileCacheDir(Context context) {
boolean external = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
if (external) {
return context.getExternalCacheDir();
} else {
return context.getCacheDir();
}
}
public static void deleteCachedFiles(Context context) {
for (File file : getFileCacheDir(context).listFiles()) {
file.delete();
}
}
}

View File

@ -265,8 +265,9 @@ public class KiwixMobileActivity extends SherlockFragmentActivity implements Act
@Override
protected void onDestroy() {
finish();
super.onDestroy();
// TODO create a base Activity class that class this.
FileUtils.deleteCachedFiles(this);
}
@Override

View File

@ -35,6 +35,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ZimContentProvider extends ContentProvider {
@ -44,10 +46,16 @@ public class ZimContentProvider extends ContentProvider {
public static final Uri UI_URI = Uri.parse("content://org.kiwix.ui/");
private static final String VIDEO_PATTERN = "([^\\s]+(\\.(?i)(3gp|mp4|m4a|aac))$)";
private static String zimFileName;
private static JNIKiwix jniKiwix;
private Pattern pattern;
private Matcher matcher;
public synchronized static String setZimFile(String fileName) {
if (!jniKiwix.loadZIM(fileName)) {
Log.e(TAG_KIWIX, "Unable to open the file " + fileName);
@ -177,7 +185,8 @@ public class ZimContentProvider extends ContentProvider {
public boolean onCreate() {
jniKiwix = new JNIKiwix();
setIcuDataDirectory();
return (true);
pattern = Pattern.compile(VIDEO_PATTERN);
return true;
}
@Override
@ -216,7 +225,16 @@ public class ZimContentProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
ParcelFileDescriptor[] pipe = null;
ParcelFileDescriptor[] pipe;
matcher = pattern.matcher(uri.toString());
if (matcher.matches()) {
try {
return saveVideoToCache(uri);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
pipe = ParcelFileDescriptor.createPipe();
@ -230,6 +248,26 @@ public class ZimContentProvider extends ContentProvider {
return (pipe[0]);
}
private ParcelFileDescriptor saveVideoToCache(Uri uri) throws IOException {
String filePath = getFilePath(uri);
String fileName = uri.toString();
fileName = fileName.substring(fileName.lastIndexOf('/') + 1, fileName.length());
File f = new File(FileUtils.getFileCacheDir(getContext()), fileName);
JNIKiwixString mime = new JNIKiwixString();
JNIKiwixInt size = new JNIKiwixInt();
byte[] data = jniKiwix.getContent(filePath, mime, size);
FileOutputStream out = new FileOutputStream(f);
out.write(data, 0, data.length);
out.flush();
return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
}
@Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
@ -275,29 +313,16 @@ public class ZimContentProvider extends ContentProvider {
TransferThread(JNIKiwix jniKiwix, Uri articleUri, OutputStream out) throws IOException {
this.articleUri = articleUri;
this.jniKiwix = jniKiwix;
Log.d(TAG_KIWIX, "Retrieving :" + articleUri.toString());
Log.d(TAG_KIWIX, "Retrieving: " + articleUri.toString());
String t = articleUri.toString();
int pos = articleUri.toString().indexOf(CONTENT_URI.toString());
if (pos != -1) {
t = articleUri.toString().substring(
CONTENT_URI.toString().length());
}
// Remove fragment (#...) as not supported by zimlib
pos = t.indexOf("#");
if (pos != -1) {
t = t.substring(0, pos);
}
String filePath = getFilePath(articleUri);
this.out = out;
this.articleZimUrl = t;
this.articleZimUrl = filePath;
}
@Override
public void run() {
byte[] buf = new byte[8192];
int len;
try {
JNIKiwixString mime = new JNIKiwixString();
JNIKiwixInt size = new JNIKiwixInt();
@ -307,10 +332,7 @@ public class ZimContentProvider extends ContentProvider {
Log.d(TAG_KIWIX, "reading " + articleZimUrl
+ "(mime: " + mime.value + ", size: " + size.value + ") finished.");
} catch (IOException e) {
Log.e(TAG_KIWIX, "Exception reading article " + articleZimUrl + " from zim file",
e);
} catch (NullPointerException e) {
} catch (IOException | NullPointerException e) {
Log.e(TAG_KIWIX, "Exception reading article " + articleZimUrl + " from zim file",
e);
} finally {
@ -321,9 +343,22 @@ public class ZimContentProvider extends ContentProvider {
"Custom exception by closing out stream for article " + articleZimUrl,
e);
}
}
}
}
private static String getFilePath(Uri articleUri) {
String filePath = articleUri.toString();
int pos = articleUri.toString().indexOf(CONTENT_URI.toString());
if (pos != -1) {
filePath = articleUri.toString().substring(
CONTENT_URI.toString().length());
}
// Remove fragment (#...) as not supported by zimlib
pos = filePath.indexOf("#");
if (pos != -1) {
filePath = filePath.substring(0, pos);
}
return filePath;
}
}