Kaydet (Commit) 143fb0a4 authored tarafından Christian Lohmaier's avatar Christian Lohmaier

move extracting assets to Java & use AssetManager to access assets

using AssetsManager in both java as well as native parts allows to
handle files both with and without compression transparently

Change-Id: If02f1159c498be7ea965fd9c217410722f2dca1f
üst ee8257a1
...@@ -11,6 +11,7 @@ package org.libreoffice.kit; ...@@ -11,6 +11,7 @@ package org.libreoffice.kit;
import android.app.Activity; import android.app.Activity;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.res.AssetManager;
import android.util.Log; import android.util.Log;
import java.io.File; import java.io.File;
...@@ -24,6 +25,7 @@ import java.nio.ByteBuffer; ...@@ -24,6 +25,7 @@ import java.nio.ByteBuffer;
public final class LibreOfficeKit public final class LibreOfficeKit
{ {
private static String LOGTAG = LibreOfficeKit.class.getSimpleName(); private static String LOGTAG = LibreOfficeKit.class.getSimpleName();
private static AssetManager mgr;
// private constructor because instantiating would be meaningless // private constructor because instantiating would be meaningless
private LibreOfficeKit() { private LibreOfficeKit() {
...@@ -34,7 +36,7 @@ public final class LibreOfficeKit ...@@ -34,7 +36,7 @@ public final class LibreOfficeKit
} }
// Trigger initialization on the JNI - LOKit side. // Trigger initialization on the JNI - LOKit side.
private static native boolean initializeNative(String dataDir, String cacheDir, String apkFile); private static native boolean initializeNative(String dataDir, String cacheDir, String apkFile, AssetManager mgr);
public static native ByteBuffer getLibreOfficeKitHandle(); public static native ByteBuffer getLibreOfficeKitHandle();
...@@ -55,6 +57,8 @@ public final class LibreOfficeKit ...@@ -55,6 +57,8 @@ public final class LibreOfficeKit
return; return;
} }
mgr = activity.getResources().getAssets();
ApplicationInfo applicationInfo = activity.getApplicationInfo(); ApplicationInfo applicationInfo = activity.getApplicationInfo();
String dataDir = applicationInfo.dataDir; String dataDir = applicationInfo.dataDir;
Log.i(LOGTAG, String.format("Initializing LibreOfficeKit, dataDir=%s\n", dataDir)); Log.i(LOGTAG, String.format("Initializing LibreOfficeKit, dataDir=%s\n", dataDir));
...@@ -83,7 +87,7 @@ public final class LibreOfficeKit ...@@ -83,7 +87,7 @@ public final class LibreOfficeKit
// TMPDIR is used by osl_getTempDirURL() // TMPDIR is used by osl_getTempDirURL()
putenv("TMPDIR=" + cacheDir); putenv("TMPDIR=" + cacheDir);
if (!initializeNative(dataDir, cacheDir, apkFile)) { if (!initializeNative(dataDir, cacheDir, apkFile, mgr)) {
Log.e(LOGTAG, "Initialize native failed!"); Log.e(LOGTAG, "Initialize native failed!");
return; return;
} }
......
...@@ -6,6 +6,9 @@ import android.content.ContentResolver; ...@@ -6,6 +6,9 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
...@@ -33,9 +36,11 @@ import java.io.File; ...@@ -33,9 +36,11 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -47,6 +52,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -47,6 +52,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
private static final String LOGTAG = "LibreOfficeMainActivity"; private static final String LOGTAG = "LibreOfficeMainActivity";
private static final String DEFAULT_DOC_PATH = "/assets/example.odt"; private static final String DEFAULT_DOC_PATH = "/assets/example.odt";
private static final String ENABLE_EXPERIMENTAL_PREFS_KEY = "ENABLE_EXPERIMENTAL"; private static final String ENABLE_EXPERIMENTAL_PREFS_KEY = "ENABLE_EXPERIMENTAL";
private static final String ASSETS_EXTRACTED_PREFS_KEY = "ASSETS_EXTRACTED";
public static LibreOfficeMainActivity mAppContext; public static LibreOfficeMainActivity mAppContext;
...@@ -147,9 +153,15 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -147,9 +153,15 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
mAppContext = this; mAppContext = this;
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mEnableEditing = PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
.getBoolean(ENABLE_EXPERIMENTAL_PREFS_KEY, false);
SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mEnableEditing = sPrefs.getBoolean(ENABLE_EXPERIMENTAL_PREFS_KEY, false);
if (sPrefs.getInt(ASSETS_EXTRACTED_PREFS_KEY, 0) != BuildConfig.VERSION_CODE) {
if(copyFromAssets(getAssets(), "unpack", getApplicationInfo().dataDir)) {
sPrefs.edit().putInt(ASSETS_EXTRACTED_PREFS_KEY, BuildConfig.VERSION_CODE).apply();
}
}
mMainHandler = new Handler(); mMainHandler = new Handler();
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
...@@ -165,6 +177,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -165,6 +177,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath()); Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
} else { } else {
// TODO: can't open the file // TODO: can't open the file
Log.e(LOGTAG, "couldn't create temporary file from "+getIntent().getData());
} }
} else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) { } else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
mInputFile = new File(getIntent().getData().getPath()); mInputFile = new File(getIntent().getData().getPath());
...@@ -217,38 +230,42 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -217,38 +230,42 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
private boolean copyFileToTemp() { private boolean copyFileToTemp() {
ContentResolver contentResolver = getContentResolver(); ContentResolver contentResolver = getContentResolver();
InputStream inputStream = null; FileChannel inputChannel = null;
FileChannel outputChannel = null;
// CSV files need a .csv suffix to be opened in Calc.
String suffix = null;
String intentType = getIntent().getType();
// K-9 mail uses the first, GMail uses the second variant.
if ("text/comma-separated-values".equals(intentType) || "text/csv".equals(intentType))
suffix = ".csv";
try { try {
inputStream = contentResolver.openInputStream(getIntent().getData()); try {
AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(getIntent().getData(), "r");
// CSV files need a .csv suffix to be opened in Calc. if (assetFD == null) {
String suffix = null; Log.e(LOGTAG, "couldn't create assetfiledescriptor from "+getIntent().getDataString());
String intentType = getIntent().getType(); return false;
// K-9 mail uses the first, GMail uses the second variant. }
if ("text/comma-separated-values".equals(intentType) || "text/csv".equals(intentType)) inputChannel = assetFD.createInputStream().getChannel();
suffix = ".csv"; mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
outputChannel = new FileOutputStream(mTempFile).getChannel();
OutputStream outputStream = new FileOutputStream(mTempFile); long bytesTransferred = 0;
byte[] buffer = new byte[4096]; // might not copy all at once, so make sure everything gets copied....
int len = 0; while (bytesTransferred < inputChannel.size()) {
while ((len = inputStream.read(buffer)) != -1) { bytesTransferred += outputChannel.transferFrom(inputChannel, bytesTransferred, inputChannel.size());
outputStream.write(buffer, 0, len); }
Log.e(LOGTAG, "Success copying "+bytesTransferred+ " bytes");
return true;
} finally {
if (inputChannel != null) inputChannel.close();
if (outputChannel != null) outputChannel.close();
} }
inputStream.close();
outputStream.close();
return true;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
return false;
} catch (IOException e) { } catch (IOException e) {
} finally { return false;
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
} }
return false;
} }
/** /**
...@@ -362,6 +379,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -362,6 +379,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
if (isFinishing()) { // Not an orientation change if (isFinishing()) { // Not an orientation change
if (mTempFile != null) { if (mTempFile != null) {
//noinspection ResultOfMethodCallIgnored
mTempFile.delete(); mTempFile.delete();
} }
} }
...@@ -423,8 +441,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -423,8 +441,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
* Hides software keyboard. * Hides software keyboard.
*/ */
private void hideSoftKeyboardDirect() { private void hideSoftKeyboardDirect() {
LayerView layerView = (LayerView) findViewById(R.id.layer_view);
if (getCurrentFocus() != null) { if (getCurrentFocus() != null) {
InputMethodManager inputMethodManager = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager inputMethodManager = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
...@@ -471,6 +487,63 @@ public class LibreOfficeMainActivity extends AppCompatActivity { ...@@ -471,6 +487,63 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
mDrawerLayout.closeDrawer(mDrawerList); mDrawerLayout.closeDrawer(mDrawerList);
} }
} }
private static boolean copyFromAssets(AssetManager assetManager,
String fromAssetPath, String targetDir) {
try {
String[] files = assetManager.list(fromAssetPath);
boolean res = true;
for (String file : files) {
String[] dirOrFile = assetManager.list(fromAssetPath+"/"+file);
if ( dirOrFile.length == 0) {
//noinspection ResultOfMethodCallIgnored
new File(targetDir).mkdirs();
res &= copyAsset(assetManager,
fromAssetPath + "/" + file,
targetDir + "/" + file);
} else
res &= copyFromAssets(assetManager,
fromAssetPath + "/" + file,
targetDir + "/" + file);
}
return res;
} catch (Exception e) {
e.printStackTrace();
Log.e(LOGTAG, "copyFromAssets failed: " + e.getMessage());
return false;
}
}
private static boolean copyAsset(AssetManager assetManager, String fromAssetPath, String toPath) {
ReadableByteChannel source = null;
FileChannel dest = null;
try {
try {
source = Channels.newChannel(assetManager.open(fromAssetPath));
dest = new FileOutputStream(toPath).getChannel();
long bytesTransferred = 0;
// might not copy all at once, so make sure everything gets copied....
ByteBuffer buffer = ByteBuffer.allocate(4096);
while (source.read(buffer)>0) {
buffer.flip();
bytesTransferred += dest.write(buffer);
buffer.clear();
}
Log.v(LOGTAG, "Success copying "+fromAssetPath+" to "+toPath + " bytes: "+bytesTransferred);
return true;
} finally {
if (dest != null) dest.close();
if (source != null) source.close();
}
} catch (FileNotFoundException e) {
Log.e(LOGTAG, "file " + fromAssetPath + " not found! " + e.getMessage());
return false;
} catch (IOException e) {
Log.e(LOGTAG, "failed to copy file " + fromAssetPath + " from assets to " + toPath + " - " + e.getMessage());
return false;
}
}
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -20,6 +20,7 @@ extern "C" { ...@@ -20,6 +20,7 @@ extern "C" {
#endif #endif
#include <osl/detail/component-mapping.h> #include <osl/detail/component-mapping.h>
#include <android/asset_manager.h>
typedef struct lo_apk_dir lo_apk_dir; typedef struct lo_apk_dir lo_apk_dir;
...@@ -38,12 +39,10 @@ JavaVM *lo_get_javavm(void); ...@@ -38,12 +39,10 @@ JavaVM *lo_get_javavm(void);
const char *lo_get_app_data_dir(void); const char *lo_get_app_data_dir(void);
#define UNPACK_TREE "/assets/unpack" AAssetManager *lo_get_native_assetmgr(void);
#define UNPACK_TREE_GZ "/assets/gz.unpack"
int setup_cdir(void); int setup_cdir(void);
int setup_assets_tree(void); int setup_assets_tree(void);
void extract_files(const char *root, const char *prefix, int gzipped);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <jni.h> #include <jni.h>
#include <android/log.h> #include <android/log.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <osl/detail/android-bootstrap.h> #include <osl/detail/android-bootstrap.h>
...@@ -34,6 +36,7 @@ extern const char* data_dir; ...@@ -34,6 +36,7 @@ extern const char* data_dir;
extern const char* cache_dir; extern const char* cache_dir;
extern void* apk_file; extern void* apk_file;
extern int apk_file_size; extern int apk_file_size;
AAssetManager* native_asset_manager;
extern void Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, jobject clazz, jstring string); extern void Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, jobject clazz, jstring string);
extern void Java_org_libreoffice_android_Bootstrap_redirect_1stdio(JNIEnv* env, jobject clazz, jboolean state); extern void Java_org_libreoffice_android_Bootstrap_redirect_1stdio(JNIEnv* env, jobject clazz, jboolean state);
...@@ -63,7 +66,7 @@ void Java_org_libreoffice_kit_LibreOfficeKit_redirectStdio ...@@ -63,7 +66,7 @@ void Java_org_libreoffice_kit_LibreOfficeKit_redirectStdio
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
(JNIEnv* env, jobject clazz, (JNIEnv* env, jobject clazz,
jstring dataDir, jstring cacheDir, jstring apkFile) jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager)
{ {
struct stat st; struct stat st;
int fd; int fd;
...@@ -76,6 +79,8 @@ jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative ...@@ -76,6 +79,8 @@ jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
(void) clazz; (void) clazz;
native_asset_manager = AAssetManager_fromJava(env, assetManager);
dataDirPath = (*env)->GetStringUTFChars(env, dataDir, NULL); dataDirPath = (*env)->GetStringUTFChars(env, dataDir, NULL);
data_dir = strdup(dataDirPath); data_dir = strdup(dataDirPath);
(*env)->ReleaseStringUTFChars(env, dataDir, dataDirPath); (*env)->ReleaseStringUTFChars(env, dataDir, dataDirPath);
...@@ -122,10 +127,6 @@ jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative ...@@ -122,10 +127,6 @@ jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
return JNI_FALSE; return JNI_FALSE;
} }
// Extract files from the .apk that can't be used mmapped directly from it
extract_files(UNPACK_TREE, UNPACK_TREE, 0);
extract_files(UNPACK_TREE_GZ, UNPACK_TREE_GZ, 1);
// LibreOfficeKit expects a path to the program/ directory // LibreOfficeKit expects a path to the program/ directory
free(full_program_dir); free(full_program_dir);
data_dir_len = strlen(data_dir); data_dir_len = strlen(data_dir);
...@@ -160,4 +161,12 @@ jobject Java_org_libreoffice_kit_LibreOfficeKit_getLibreOfficeKitHandle ...@@ -160,4 +161,12 @@ jobject Java_org_libreoffice_kit_LibreOfficeKit_getLibreOfficeKitHandle
return (*env)->NewDirectByteBuffer(env, (void*) aOffice, sizeof(LibreOfficeKit)); return (*env)->NewDirectByteBuffer(env, (void*) aOffice, sizeof(LibreOfficeKit));
} }
__attribute__ ((visibility("default")))
AAssetManager *
lo_get_native_assetmgr(void)
{
return native_asset_manager;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -311,10 +311,6 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri ...@@ -311,10 +311,6 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri
if (!setup_assets_tree()) if (!setup_assets_tree())
return JNI_FALSE; return JNI_FALSE;
// Extract files from the .apk that can't be used mmapped directly from it
extract_files(UNPACK_TREE, UNPACK_TREE, 0);
extract_files(UNPACK_TREE_GZ, UNPACK_TREE_GZ, 1);
return JNI_TRUE; return JNI_TRUE;
} }
...@@ -635,184 +631,6 @@ lo_apk_lstat(const char *path, ...@@ -635,184 +631,6 @@ lo_apk_lstat(const char *path,
return -1; return -1;
} }
static int
mkdir_p(const char *dirname)
{
char *p = malloc(strlen(dirname) + 1);
const char *q = dirname + 1;
const char *slash;
do {
slash = strchr(q, '/');
if (slash == NULL)
slash = q + strlen(q);
memcpy(p, dirname, slash-dirname);
p[slash-dirname] = '\0';
if (mkdir(p, 0700) == -1 && errno != EEXIST) {
LOGE("mkdir_p: Could not create %s: %s", p, strerror(errno));
free(p);
return 0;
}
if (*slash)
q = slash + 1;
} while (*slash);
free(p);
return 1;
}
static int
extract_gzipped(const char *filename,
const char *apkentry,
int size,
FILE *f)
{
gzFile gzfd;
int gzerrno;
int nbytes;
char buf[5000];
int total = 0;
char *tmpname;
FILE *tmp;
tmpname = malloc(strlen(cache_dir) + strlen("/tmp.gz") + 1);
strcpy(tmpname, cache_dir);
strcat(tmpname, "/tmp.gz");
tmp = fopen(tmpname, "w+");
unlink(tmpname);
if (tmp == NULL) {
LOGE("extract_gzipped: could not create %s: %s", tmpname, strerror(errno));
free(tmpname);
return 0;
}
if (fwrite(apkentry, size, 1, tmp) != 1) {
LOGE("extract_gzipped: could not write gzipped entry to %s: %s", tmpname, strerror(errno));
fclose(tmp);
free(tmpname);
return 0;
}
free(tmpname);
rewind(tmp);
gzfd = gzdopen(fileno(tmp), "rb");
if (gzfd == NULL) {
LOGE("extract_gzipped: gzdopen failed");
fclose(tmp);
return 0;
}
while ((nbytes = gzread(gzfd, buf, sizeof(buf))) > 0) {
fwrite(buf, nbytes, 1, f);
total += nbytes;
}
if (nbytes == -1) {
LOGE("extract_gzipped: Could not gzread from %s: %s", filename, gzerror(gzfd, &gzerrno));
return total;
}
if (gzclose(gzfd) == -1) {
LOGE("extract_gzipped: gzclose failed");
return total;
}
return total;
}
void
extract_files(const char *root,
const char *prefix,
int gzipped)
{
lo_apk_dir *tree = lo_apk_opendir(prefix);
struct dirent *dent;
if (tree == NULL)
return;
while ((dent = lo_apk_readdir(tree)) != NULL) {
if (strcmp(dent->d_name, ".") == 0 ||
strcmp(dent->d_name, "..") == 0)
continue;
if (dent->d_type == DT_DIR) {
char *subdir = malloc(strlen(prefix) + 1 + strlen(dent->d_name) + 1);
strcpy(subdir, prefix);
strcat(subdir, "/");
strcat(subdir, dent->d_name);
extract_files(root, subdir, gzipped);
free(subdir);
} else {
char *filename;
char *newfilename;
const char *apkentry;
size_t size;
struct stat st;
FILE *f;
filename = malloc(strlen(prefix) + 1 + strlen(dent->d_name) + 1);
strcpy(filename, prefix);
strcat(filename, "/");
strcat(filename, dent->d_name);
apkentry = lo_apkentry(filename, &size);
if (apkentry == NULL) {
LOGE("extract_files: Could not find %s in .apk", filename);
free(filename);
continue;
}
newfilename = malloc(strlen(data_dir) + 1 + strlen(prefix) - strlen(root) + strlen(dent->d_name) + 1);
strcpy(newfilename, data_dir);
strcat(newfilename, "/");
strcat(newfilename, prefix + strlen(root) + 1);
if (!mkdir_p(newfilename)) {
free(filename);
free(newfilename);
continue;
}
strcat(newfilename, "/");
strcat(newfilename, dent->d_name);
if (stat(newfilename, &st) == 0 &&
(gzipped || st.st_size == (long long) size)) {
free(filename);
free(newfilename);
continue;
}
f = fopen(newfilename, "w");
if (f == NULL) {
LOGE("extract_files: Could not open %s for writing: %s", newfilename, strerror(errno));
free(filename);
free(newfilename);
continue;
}
if (!gzipped) {
if (fwrite(apkentry, size, 1, f) != 1) {
LOGE("extract_files: Could not write %lld bytes to %s: %s", (long long) size, newfilename, strerror(errno));
} else {
LOGI("extract_files: Copied %s to %s: %lld bytes", filename, newfilename, (long long) size);
}
} else {
size = extract_gzipped(filename, apkentry, size, f);
LOGI("extract_files: Decompressed %s to %s: %lld bytes", filename, newfilename, (long long) size);
}
fclose(f);
free(filename);
free(newfilename);
}
}
lo_apk_closedir(tree);
}
/* Android's JNI works only to libraries loaded through Java's /* Android's JNI works only to libraries loaded through Java's
* System.loadLibrary(), it seems. But now with just one big app-specific .so * System.loadLibrary(), it seems. But now with just one big app-specific .so
* on Android, that would not be a problem, but for historical reasons, we * on Android, that would not be a problem, but for historical reasons, we
......
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
#ifdef ANDROID #ifdef ANDROID
#include <osl/detail/android-bootstrap.h> #include <osl/detail/android-bootstrap.h>
#include <android/log.h>
#include <android/asset_manager.h>
#endif #endif
/******************************************************************* /*******************************************************************
...@@ -830,6 +832,21 @@ openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags, ...@@ -830,6 +832,21 @@ openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags,
*/ */
if (strncmp (cpFilePath, "/assets/", sizeof ("/assets/") - 1) == 0) if (strncmp (cpFilePath, "/assets/", sizeof ("/assets/") - 1) == 0)
{ {
void* address;
size_t size;
AAssetManager* mgr = lo_get_native_assetmgr();
AAsset* asset = AAssetManager_open(mgr, cpFilePath + sizeof("/assets/")-1, AASSET_MODE_BUFFER);
if (NULL == asset) {
address = NULL;
errno = ENOENT;
__android_log_print(ANDROID_LOG_ERROR,"libo:sal/osl/unx/file", "failed to open %s", cpFilePath);
return osl_File_E_NOENT;
} else {
size = AAsset_getLength(asset);
address = malloc (sizeof(char)*size);
AAsset_read (asset,address,size);
AAsset_close(asset);
}
if (uFlags & osl_File_OpenFlag_Write) if (uFlags & osl_File_OpenFlag_Write)
{ {
// It seems to work better to silently "open" it read-only // It seems to work better to silently "open" it read-only
...@@ -837,15 +854,7 @@ openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags, ...@@ -837,15 +854,7 @@ openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags,
// loading a document from /assets fails with that idiotic // loading a document from /assets fails with that idiotic
// "General Error" dialog... // "General Error" dialog...
} }
void *address;
size_t size;
address = lo_apkentry(cpFilePath, &size);
SAL_INFO("sal.file", "osl_openFile(" << cpFilePath << ") => " << address); SAL_INFO("sal.file", "osl_openFile(" << cpFilePath << ") => " << address);
if (address == NULL)
{
errno = ENOENT;
return osl_File_E_NOENT;
}
return openMemoryAsFile(address, size, pHandle, cpFilePath); return openMemoryAsFile(address, size, pHandle, cpFilePath);
} }
#endif #endif
...@@ -1043,6 +1052,10 @@ SAL_CALL osl_closeFile( oslFileHandle Handle ) ...@@ -1043,6 +1052,10 @@ SAL_CALL osl_closeFile( oslFileHandle Handle )
if (pImpl->m_kind == FileHandle_Impl::KIND_MEM) if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
{ {
#ifdef ANDROID
free(pImpl->m_buffer);
pImpl->m_buffer = NULL;
#endif
delete pImpl; delete pImpl;
return osl_File_E_None; return osl_File_E_None;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment