mobile: add sample android application (HelloECL)

Developed by Sylvain Agenau, added to the repository by Evrim Ulu with
a few minor fixes by Daniel Kochmański.
This commit is contained in:
Evrim Ulu 2015-03-25 22:06:53 +02:00 committed by Daniel Kochmański
parent d7776157d6
commit 641a12b4e1
21 changed files with 753 additions and 0 deletions

12
README.android Normal file
View file

@ -0,0 +1,12 @@
To build:
$ export ANDROID_NDK_ROOT=Path to NDK
$ ./configure.android
This will create a 32-bit version of ECL to cross-compile.
Then it will compile an ARM 32-bit ECL into android/install/android.
Please see the sample application in contrib/android.
evrim ulu <evrimulu@gmail.com>
March 2015

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

33
examples/android/.project Normal file
View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>HelloEclActivity</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,4 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lisp.ecl"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:label="@string/app_name"
android:debuggable="true">
<activity android:name="HelloEclActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

14
examples/android/README Normal file
View file

@ -0,0 +1,14 @@
This project is a base project for ECL Android.
It is created by Sylvain Ageneau <ageneau@gmail.com>.
Original location of this project is:
http://github.com/ageneau/ecl-android
Instructions:
$ android update project -t android-19 -p .
$ ndk-build
$ ant debug install
Please direct further questions to ecl-devel@common-lisp.net
evrim ulu <evrimulu@gmail.com>
March 2015.

View file

@ -0,0 +1,17 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

View file

@ -0,0 +1,57 @@
(in-package :cl-user)
(format t "ECL (Embeddable Common-Lisp) ~A (git:~D)~%"
(lisp-implementation-version)
(ext:lisp-implementation-vcs-id))
(require :SOCKETS)
(require :ASDF)
(setq *default-directory*
*default-pathname-defaults*)
(defvar *ecl-home* *default-directory*)
(ext:setenv "HOME" (namestring *ecl-home*))
(pushnew (namestring *default-pathname-defaults*)
asdf:*central-registry*)
(asdf:oos 'asdf:load-op :swank)
(swank-loader:init :load-contribs t
:setup t
:delete t
:quiet nil)
;; The following "patches" swank to work correctly on android/iOS
(in-package :swank/backend)
(defimplementation lisp-implementation-program ()
"Return the argv[0] of the running Lisp process, or NIL."
;; (lisp-implementation-type)
nil)
(in-package :swank)
(defun repl-input-stream-read (connection stdin)
(loop
(let* ((socket (connection.socket-io connection))
(inputs (list socket #+nil stdin))
(ready (wait-for-input inputs)))
(describe (list 'hobaa connection stdin socket inputs ready))
(cond ((eq ready :interrupt)
(check-slime-interrupts))
((member socket ready)
;; A Slime request from Emacs is pending; make sure to
;; redirect IO to the REPL buffer.
(with-simple-restart (process-input "Continue reading input.")
(let ((*sldb-quit-restart* (find-restart 'process-input)))
(with-io-redirection (connection)
(handle-requests connection t)))))
((member stdin ready)
;; User typed something into the *inferior-lisp* buffer,
;; so do not redirect.
(return (read-non-blocking stdin)))
(t (assert (null ready)))))))
(mp:process-run-function
"SLIME-listener"
(lambda ()
(swank:create-server :port 4005
:dont-close t)))
(cond ((probe-file #P"user.lisp")
(load "user")))

View file

@ -0,0 +1,51 @@
(in-package :cl-user)
(require 'bytecmp)
(setq *default-directory*
*default-pathname-defaults*)
(defun sysinfo (&optional (out *standard-output*))
"Print the current environment to a stream."
(declare (stream out))
(format out "~&~%~75~~%~75,,,'-:@<<{[ The current environment ]}>~>~%~
Implementation:~20t~a~%~7tversion:~20t~a~%Machine: type:~20t~a
~7tversion:~20t~a~%~6tinstance:~20t~a~%Opeating System:~19t"
(lisp-implementation-type) (lisp-implementation-version)
(machine-type) (machine-version) (machine-instance))
#+darwin (princ " Darwin")
#+unix (princ " Unix")
(format out "~%Software: type:~20t~a~%~7tversion:~20t~a~%Site:~20t~a (~a)
User home:~20t~a~%Current directory:~20t~a~%Default pathname:~20t~a~%"
(software-type) (software-version) (long-site-name)
(short-site-name) (user-homedir-pathname) *default-directory*
*default-pathname-defaults*)
(format out "Features: ~s.
Modules:~s.~%
Current package:~s~%"
*features* *modules* *package*)
(flet ((exdi (fl) (integer-length (nth-value 1 (decode-float fl)))))
(format out "Fixnum length:~25t~3d bits
Short Floats:~25t~3d bits exponent, ~3d bits significand (mantissa)
Single Floats:~25t~3d bits exponent, ~3d bits significand (mantissa)
Double Floats:~25t~3d bits exponent, ~3d bits significand (mantissa)
Long Floats:~25t~3d bits exponent, ~3d bits significand (mantissa)~%"
(integer-length most-positive-fixnum)
(exdi most-positive-short-float)
(float-digits most-positive-short-float)
(exdi most-positive-single-float)
(float-digits most-positive-single-float)
(exdi most-positive-double-float)
(float-digits most-positive-double-float)
(exdi most-positive-long-float)
(float-digits most-positive-long-float)))
(dolist (sy '(array-total-size-limit array-rank-limit array-dimension-limit
lambda-parameters-limit call-arguments-limit
multiple-values-limit char-code-limit))
(format out " ~a:~30t~15:d~%" sy (symbol-value sy)))
(format out "lambda-list-keywords:~s~%"
lambda-list-keywords)
(format out "Internal time unit:~25t~f sec~%*gensym-counter*:~25t~:d
Current time:~25t" (/ internal-time-units-per-second) *gensym-counter*)
(format out "~a" (get-universal-time))
(format out "~%~75~~%") (room) (values))
(sysinfo)

View file

@ -0,0 +1,39 @@
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
BASE_PATH := $(call my-dir)
include $(CLEAR_VARS)
ifeq ($(TARGET_ARCH),x86)
PLATFORM := androidx86
else
PLATFORM := android
endif
ECL_HOME := ../../android/install/$(PLATFORM)
ECL_VER := $(shell basename $(ECL_HOME)/lib/ecl-* |cut -d "-" -f2)
LOCAL_MODULE := ecl_android
LOCAL_PATH := $(BASE_PATH)
LOCAL_SRC_FILES := org_lisp_ecl_EmbeddedCommonLisp.c ecl_boot.c
LOCAL_CFLAGS += -I$(ECL_HOME)/include
LOCAL_CFLAGS += -g -Wall -DANDROID
LOCAL_LDLIBS := -L$(ECL_HOME)/lib
LOCAL_LDLIBS += -L$(ECL_HOME)/lib/ecl-$(ECL_VER)
LOCAL_LDLIBS += -lecl -lasdf -leclgmp -lsockets -llog
LOCAL_LDLIBS += -lsb-bsd-sockets -lserve-event -lecl-help
LOCAL_LDLIBS += -lecl-cdb -leclgc -leclatomic
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,88 @@
#include <stdlib.h>
#include <ecl/ecl.h>
#if ANDROID
#include <android/log.h>
#endif
#if ANDROID
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__))
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "native-activity", __VA_ARGS__))
#else
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#endif
#include "ecl_boot.h"
#ifdef __cplusplus
#define ECL_CPP_TAG "C"
#else
#define ECL_CPP_TAG
#endif
extern ECL_CPP_TAG void main_lib_ASDF();
extern ECL_CPP_TAG void main_lib_SOCKETS();
extern ECL_CPP_TAG void main_lib_SB_BSD_SOCKETS();
extern ECL_CPP_TAG void main_lib_SERVE_EVENT();
extern ECL_CPP_TAG void main_lib_ECL_CDB();
extern ECL_CPP_TAG void main_lib_ECL_HELP();
extern void loadLispFromAssets(char* fn);
int ecl_boot(const char *root_dir)
{
char *ecl = "ecl";
char tmp[2048];
sprintf(tmp, "%s/", root_dir);
setenv("ECLDIR", tmp, 1);
// ecl_set_option(ECL_OPT_TRAP_SIGFPE, 0);
// ecl_set_option(ECL_OPT_TRAP_SIGSEGV, 0);
// ecl_set_option(ECL_OPT_TRAP_SIGINT, 0);
// ecl_set_option(ECL_OPT_TRAP_SIGILL, 0);
// ecl_set_option(ECL_OPT_TRAP_SIGBUS, 0);
// ecl_set_option(ECL_OPT_TRAP_INTERRUPT_SIGNAL, 0);
// ecl_set_option(ECL_OPT_SIGNAL_HANDLING_THREAD, 0);
// ecl_set_option(ECL_OPT_INCREMENTAL_GC, 0);
cl_boot(1, &ecl);
main_lib_ECL_HELP();
main_lib_ASDF();
main_lib_SOCKETS();
si_safe_eval(3, c_string_to_object("(format t \"ECL_BOOT, features = ~A ~%\" *features*)"), Cnil, OBJNULL);
si_safe_eval(3, c_string_to_object("(format t \"(truename SYS:): ~A)\" (truename \"SYS:\"))"), Cnil, OBJNULL);
LOGI("ALL LOADED\n");
ecl_toplevel(root_dir);
return 0;
}
void ecl_toplevel(const char *home)
{
char tmp[2048];
LOGI("START TOP LEVEL\n");
CL_CATCH_ALL_BEGIN(ecl_process_env())
{
sprintf(tmp, "(setq *default-pathname-defaults* #p\"%s/\")", home);
si_safe_eval(3, c_string_to_object(tmp), Cnil, OBJNULL);
si_select_package(ecl_make_simple_base_string("CL-USER", 7));
si_safe_eval(3, c_string_to_object("(load \"init\")"), Cnil, OBJNULL);
} CL_CATCH_ALL_END;
LOGI("EXIT TOP LEVEL\n");
}

View file

@ -0,0 +1,8 @@
#ifndef _ECL_BOOT_H_
#define _ECL_BOOT_H_
int ecl_boot(const char *root_dir);
void ecl_toplevel(const char *home);
void eclshell_show(char *message);
#endif

View file

@ -0,0 +1,134 @@
#include <assert.h>
#if ANDROID
#include <android/log.h>
#endif
#include <string.h>
#include <jni.h>
#include <pthread.h>
#include <stdio.h>
#include <ecl/ecl.h>
#include "ecl_boot.h"
#if ANDROID
#define ECL_TAG "ecl-native"
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, ECL_TAG, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, ECL_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, ECL_TAG, __VA_ARGS__))
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ECL_TAG, __VA_ARGS__))
#else
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#endif
#define jni_ecl_read_from_string(x) si_string_to_object(1, x)
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: start
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_org_lisp_ecl_EmbeddedCommonLisp_start(JNIEnv *env, jobject this,
jstring path) {
const char *lisp_dir = (*env)->GetStringUTFChars(env, path, NULL);
LOGI("ECL starting: *default-pathname-defaults* to: %s\n", lisp_dir);
ecl_boot(lisp_dir);
LOGI("ECL started.");
};
/* This was fun to make UTF8 work across Java-C-Lisp boundaries.
-evrim, 2014. */
cl_object java_string_to_ecl_string(JNIEnv *env, jstring str) {
const jchar *txt = (*env)->GetStringChars(env, str, NULL);
jsize len = (*env)->GetStringLength(env, str);
cl_object ecl_txt = ecl_alloc_simple_extended_string(len);
cl_index i;
for (i=0;i<len;i++) {
ecl_txt->string.self[i] = txt[i];
};
(*env)->ReleaseStringChars(env, str, txt);
return ecl_txt;
}
jstring ecl_object_to_java_string(JNIEnv *env, cl_object o) {
jstring ret;
if (ECL_EXTENDED_STRING_P(o)) {
LOGI("ecl->java extended string of fillp: %d, dim: %d",
o->string.fillp,
o->string.dim);
jsize len = o->string.fillp;
jchar *arr = malloc(sizeof(jchar)*(len+1));
cl_index i;
for (i=0; i<len; i++) {
arr[i] = o->string.self[i];
}
arr[len] = 0;
ret = (*env)->NewString(env, arr, len);
free(arr);
} else if (ECL_STRINGP(o)) {
LOGI("ecl->java base string of len %d: %s",
o->base_string.dim,
o->base_string.self);
ret = (*env)->NewStringUTF(env,
(const char*)o->base_string.self);
} else {
LOGI("ecl->java not a string, coercing");
return ecl_object_to_java_string(env, cl_princ_to_string(o));
}
return ret;
}
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: exec
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_org_lisp_ecl_EmbeddedCommonLisp_exec(JNIEnv *env, jobject this, jstring str) {
jstring ret;
cl_object txt = java_string_to_ecl_string(env, str);
cl_object result = si_safe_eval(3, jni_ecl_read_from_string(txt), Cnil, OBJNULL);
if (result) {
ret = ecl_object_to_java_string(env, result);
} else {
ret = (*env)->NewStringUTF(env, "ERROR in eval");
}
return ret;
};
#undef jni_ecl_read_from_string
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: exec_
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_org_lisp_ecl_EmbeddedCommonLisp_exec_(JNIEnv *env, jobject this, jstring str) {
jstring ret;
const char *cmd = (*env)->GetStringUTFChars(env, str, NULL);
cl_object result = si_safe_eval(3, c_string_to_object(cmd),
Cnil, OBJNULL);
if (result) {
cl_object out = si_coerce_to_base_string(cl_princ_to_string(result));
ret = (*env)->NewStringUTF(env, (const char*) out->base_string.self);
} else {
ret = (*env)->NewStringUTF(env, "ERROR in eval");
}
return ret;
};

View file

@ -0,0 +1,37 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_lisp_ecl_EmbeddedCommonLisp */
#ifndef _Included_org_lisp_ecl_EmbeddedCommonLisp
#define _Included_org_lisp_ecl_EmbeddedCommonLisp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: start
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_lisp_ecl_EmbeddedCommonLisp_start
(JNIEnv *, jobject, jstring);
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: exec
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_lisp_ecl_EmbeddedCommonLisp_exec
(JNIEnv *, jobject, jstring);
/* /\* */
/* * Class: org_lisp_ecl_EmbeddedCommonLisp */
/* * Method: botExec */
/* * Signature: (Ljava/lang/String;)Ljava/lang/String; */
/* *\/ */
/* JNIEXPORT jstring JNICALL Java_org_lisp_ecl_EmbeddedCommonLisp_exec_ */
/* (JNIEnv *, jobject, jstring); */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View file

@ -0,0 +1,14 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19

View file

@ -0,0 +1,13 @@
<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, HelloEclActivity"
/>
</LinearLayout>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Single menu item
Set id, icon and Title for each menu item
-->
<item android:id="@+id/menu_uncompress"
android:title="Uncompress assets" />
</menu>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HelloEclActivity</string>
</resources>

View file

@ -0,0 +1,19 @@
package org.lisp.ecl;
import android.util.Log;
public class EmbeddedCommonLisp {
private static String TAG = "EmbeddedCommonLisp";
public void start() {
start(System.getenv("user.dir"));
}
public native void start(String path);
public native String exec(String string);
// public native String botExec(String string);
static {
System.loadLibrary("ecl_android");
Log.w(TAG,"Done loading library");
}
}

View file

@ -0,0 +1,154 @@
package org.lisp.ecl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
public class HelloEclActivity extends Activity
{
private static String TAG = "HelloEcl";
private static String RESOURCES_DIR = "lisp";
private static String APP_RESOURCES_DIR = "resources";
private EmbeddedCommonLisp ecl = new EmbeddedCommonLisp();
private static boolean DEBUG = false;
static AssetManager assetManager;
static File uncompressedFilesDir;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
assetManager = getAssets();
SharedPreferences settings = getPreferences(MODE_PRIVATE);
boolean assetsUncompressed = settings.getBoolean("assetsUncompressed", false);
uncompressedFilesDir = getDir(APP_RESOURCES_DIR,MODE_PRIVATE);
if(!assetsUncompressed)
{
uncompressDir(RESOURCES_DIR,uncompressedFilesDir);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("assetsUncompressed", true);
editor.commit();
}
Log.w(TAG,"ECL starting.");
ecl.start(getResourcesPath());
Log.w(TAG,"ECL Started");
setContentView(R.layout.main);
String result = ecl.exec("(format nil \"Hello from lisp\")");
System.out.println("Result: " + result);
Context context = getApplicationContext();
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, result, duration);
toast.show();
}
public void uncompressDir(String in, File out)
{
try
{
String[] files = assetManager.list(in);
Log.w(TAG,"Uncompressing: " + files.length + " files");
for(int i=0; i<files.length; i++)
{
Log.w(TAG,"Uncompressing: " + files[i]);
File fileIn = new File(in,files[i]);
File fileOut = new File(out,files[i]);
try
{
uncompressFile(fileIn,fileOut);
}
catch(FileNotFoundException e)
{
// fileIn is a directory, uncompress the subdir
if(!fileOut.isDirectory())
{
Log.w(TAG,"Creating dir: " + fileOut.getAbsolutePath());
fileOut.mkdir();
}
uncompressDir(fileIn.getPath(), fileOut);
}
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
// Initiating Menu XML file (menu.xml)
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.layout.menu, menu);
return true;
}
/**
* Event Handling for Individual menu item selected
* Identify single menu item by it's id
* */
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.menu_uncompress:
uncompressDir(RESOURCES_DIR,uncompressedFilesDir);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public static String getResourcesPath()
{
return uncompressedFilesDir.getAbsolutePath();
}
public static void uncompressFile(File fileIn,File fileOut)
throws IOException
{
InputStream in = assetManager.open(fileIn.getPath(),
android.content.res.AssetManager.ACCESS_RANDOM);
OutputStream out = new FileOutputStream(fileOut);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
in.close();
out.close();
Log.i(TAG,"File copied.");
}
}