app2sd support for shared libraries

This commit is contained in:
pelya
2011-02-18 16:09:20 +00:00
parent 881ebab0b0
commit 4f3665edef
10 changed files with 197 additions and 30 deletions

View File

@@ -488,7 +488,7 @@ if [ "$MultiABI" = "y" ] ; then
else
MultiABI="armeabi"
fi
LibrariesToLoad="System.loadLibrary(\\\"sdl-$LibSdlVersion\\\");"
LibrariesToLoad="\\\"sdl-$LibSdlVersion\\\""
StaticLibraries=`grep 'APP_AVAILABLE_STATIC_LIBS' project/jni/SettingsTemplate.mk | sed 's/.*=\(.*\)/\1/'`
for lib in $CompiledLibraries; do
process=true
@@ -496,7 +496,7 @@ for lib in $CompiledLibraries; do
if [ "$lib" = "$lib1" ]; then process=false; fi
done
if $process; then
LibrariesToLoad="$LibrariesToLoad System.loadLibrary(\\\"$lib\\\");"
LibrariesToLoad="$LibrariesToLoad, \\\"$lib\\\""
fi
done
@@ -545,7 +545,7 @@ cat project/src/Globals.java | \
sed "s/public static int AppTouchscreenKeyboardKeysAmountAutoFire = .*;/public static int AppTouchscreenKeyboardKeysAmountAutoFire = $AppTouchscreenKeyboardKeysAmountAutoFire;/" | \
sed "s%public static String ReadmeText = .*%public static String ReadmeText = \"$ReadmeText\".replace(\"^\",\"\\\n\");%" | \
sed "s%public static String CommandLine = .*%public static String CommandLine = \"$AppCmdline\";%" | \
sed "s/public LoadLibrary() .*/public LoadLibrary() { $LibrariesToLoad };/" > \
sed "s/public static String AppLibraries.*/public static String AppLibraries[] = { $LibrariesToLoad };/" > \
project/src/Globals.java.1
mv -f project/src/Globals.java.1 project/src/Globals.java

35
app2sd.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
APK=$1
if [ -z "$APK" ] ; then
APK=project/bin/DemoActivity-debug.apk
fi
echo Moving shared libraries on $APK to SD card
APK=`pwd`/$APK
[ -e $APK ] || { echo File $APK does not exist; exit 1; }
TMPDIR=app2sd-$$
mkdir -p $TMPDIR
cd $TMPDIR
unzip $APK "lib/armeabi/*" || { echo "This apk file has already been app2sd-ed, or improperly compiled"; exit 1; }
zip -j bindata.zip lib/armeabi/*
mkdir assets
split -b 1048576 -d -a 1 bindata.zip assets/bindata
rm bindata.zip
zip -d $APK "lib/armeabi/*" "META-INF/*"
zip -0 $APK assets/bindata*
jarsigner -verbose -keystore ~/.android/debug.keystore -storepass "android" $APK androiddebugkey
zipalign 4 $APK $APK-tmp
mv -f $APK-tmp $APK
cd ..
rm -rf $TMPDIR

View File

@@ -9,6 +9,8 @@ import android.view.KeyEvent;
class Globals {
public static String ApplicationName = "CommanderGenius";
public static String AppLibraries[] = { "sdl-1.2", };
public static final boolean Using_SDL_1_3 = false;
// Should be zip file
@@ -105,7 +107,3 @@ class Globals {
public static boolean SmoothVideo = false;
public static boolean MultiThreadedVideo = SwVideoMode;
}
class LoadLibrary {
public LoadLibrary() { System.loadLibrary("sdl-1.2"); };
}

View File

@@ -24,6 +24,16 @@ import android.app.PendingIntent;
import android.content.Intent;
import android.view.View.OnKeyListener;
import java.util.LinkedList;
import java.io.SequenceInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class MainActivity extends Activity {
@@ -81,7 +91,7 @@ public class MainActivity extends Activity {
if(mAudioThread == null) // Starting from background (should not happen)
{
System.out.println("libSDL: Loading libraries");
mLoadLibraryStub = new LoadLibrary();
LoadLibraries();
mAudioThread = new AudioThread(this);
System.out.println("libSDL: Loading settings");
Settings.Load(this);
@@ -223,19 +233,13 @@ public class MainActivity extends Activity {
{
if(_screenKeyboard == null)
return;
String text = _screenKeyboard.getText().toString();
if( mGLView != null )
synchronized(textInput)
{
synchronized(textInput) {
for(int i = 0; i < text.length(); i++)
{
DemoRenderer.nativeTextInput( (int)text.charAt(i), (int)text.codePointAt(i) );
//textInput.addLast((int)text.charAt(i));
//textInput.addLast((int)text.codePointAt(i));
}
DemoRenderer.nativeTextInput( 13, 13 ); // send return
//textInput.addLast(13);
//textInput.addLast(13);
String text = _screenKeyboard.getText().toString();
for(int i = 0; i < text.length(); i++)
{
DemoRenderer.nativeTextInput( (int)text.charAt(i), (int)text.codePointAt(i) );
}
}
_videoLayout.removeView(_screenKeyboard);
@@ -255,12 +259,19 @@ public class MainActivity extends Activity {
myKeyListener(MainActivity parent) { _parent = parent; };
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER))
if ((event.getAction() == KeyEvent.ACTION_UP) && ((keyCode == KeyEvent.KEYCODE_ENTER) || (keyCode == KeyEvent.KEYCODE_BACK)))
{
_parent.hideScreenKeyboard();
if(keyCode == KeyEvent.KEYCODE_ENTER)
{
synchronized(textInput)
{
DemoRenderer.nativeTextInput( 13, 13 ); // send return
}
}
return true;
}
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_CLEAR))
if ((event.getAction() == KeyEvent.ACTION_UP) && (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_CLEAR))
{
synchronized(textInput) {
DemoRenderer.nativeTextInput( 8, 8 );
@@ -376,13 +387,104 @@ public class MainActivity extends Activity {
NotificationManager NotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationManager.cancel(NOTIFY_ID);
}
public void LoadLibraries()
{
try
{
for(String l : Globals.AppLibraries)
{
System.loadLibrary(l);
}
}
catch ( UnsatisfiedLinkError e )
{
try {
System.out.println("libSDL: Extracting APP2SD-ed libs");
InputStream in = null;
try
{
for( int i = 0; ; i++ )
{
InputStream in2 = getAssets().open("bindata" + String.valueOf(i));
if( in == null )
in = in2;
else
in = new SequenceInputStream( in, in2 );
}
}
catch( IOException ee ) { }
if( in == null )
throw new RuntimeException("libSDL: Extracting APP2SD-ed libs failed, the .apk file packaged incorrectly");
ZipInputStream zip = new ZipInputStream(in);
File cacheDir = getCacheDir();
try {
cacheDir.mkdirs();
} catch( SecurityException ee ) { };
byte[] buf = new byte[16384];
while(true)
{
ZipEntry entry = null;
entry = zip.getNextEntry();
/*
if( entry != null )
System.out.println("Extracting lib " + entry.getName());
*/
if( entry == null )
{
System.out.println("Extracting libs finished");
break;
}
if( entry.isDirectory() )
{
System.out.println("Warning '" + entry.getName() + "' is a directory");
continue;
}
OutputStream out = null;
String path = cacheDir.getAbsolutePath() + "/" + entry.getName();
System.out.println("Saving to file '" + path + "'");
out = new FileOutputStream( path );
int len = zip.read(buf);
while (len >= 0)
{
if(len > 0)
out.write(buf, 0, len);
len = zip.read(buf);
}
out.flush();
out.close();
}
for(String l : Globals.AppLibraries)
{
String libname = System.mapLibraryName(l);
File libpath = new File(cacheDir, libname);
System.out.println("libSDL: loading lib " + libpath.getPath());
System.load(libpath.getPath());
libpath.delete();
}
}
catch ( Exception ee )
{
System.out.println("libSDL: Error: " + e.toString());
}
}
};
public FrameLayout getVideoLayout() { return _videoLayout; }
static int NOTIFY_ID = 12367098; // Random ID
private static DemoGLSurfaceView mGLView = null;
private static LoadLibrary mLoadLibraryStub = null;
private static AudioThread mAudioThread = null;
private static DataDownloader downloader = null;

View File

@@ -18,6 +18,7 @@ import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import android.os.Environment;
import java.io.File;
import android.widget.TextView;
import java.lang.Thread;
@@ -205,8 +206,27 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer {
// Thread.currentThread().setPriority((Thread.currentThread().getPriority() + Thread.MIN_PRIORITY)/2);
mGlContextLost = false;
System.loadLibrary("application");
System.loadLibrary("sdl_main");
String libs[] = { "application", "sdl_main" };
try
{
for(String l : libs)
{
System.loadLibrary(l);
}
}
catch ( UnsatisfiedLinkError e )
{
for(String l : libs)
{
String libname = System.mapLibraryName(l);
File libpath = new File(context.getCacheDir(), libname);
System.out.println("libSDL: loading lib " + libpath.getPath());
System.load(libpath.getPath());
libpath.delete();
}
}
Settings.Apply(context);
accelerometer = new AccelerometerReader(context);
// Tweak video thread priority, if user selected big audio buffer

View File

@@ -1,14 +1,15 @@
# The application settings for Android libSDL port
AppSettingVersion=16
AppSettingVersion=17
LibSdlVersion=1.2
AppName="Free Heroes 2"
AppFullName=net.sourceforge.fheroes2
ScreenOrientation=h
InhibitSuspend=n
AppDataDownloadUrl="Game data|data8.zip^Heroes 2 DEMO data files (45 Mb)|http://downloads.pcworld.com/pub/new/fun_and_games/adventure_strategy/h2demo.zip|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/h2demo.zip/download^MIDI music support (18 Mb)|http://sourceforge.net/projects/libsdl-android/files/timidity.zip/download^Essential map pack (9 Mb)|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/EssentialMapPack.zip/download^Additional map pack (95 Mb)|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/AdditionalMapPack.zip/download^Mega map pack (280 Mb)|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/MegaMapPack.zip/download^Russian translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-ru.cfg/download^Czech translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-cs.cfg/download^Spanish translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-es.cfg/download^French translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-fr.cfg/download^Hungarian translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-hu.cfg/download^Polish translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-pl.cfg/download^Portugese translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-pt.cfg/download^Swedish translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-sv.cfg/download"
AppDataDownloadUrl="Game data|data9.zip^Heroes 2 DEMO data files (45 Mb)|http://downloads.pcworld.com/pub/new/fun_and_games/adventure_strategy/h2demo.zip|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/h2demo.zip/download^MIDI music support (18 Mb)|http://sourceforge.net/projects/libsdl-android/files/timidity.zip/download^Essential map pack (9 Mb)|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/EssentialMapPack.zip/download^Additional map pack (95 Mb)|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/AdditionalMapPack.zip/download^Mega map pack (280 Mb)|http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/MegaMapPack.zip/download^Russian translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-ru.cfg/download^Czech translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-cs.cfg/download^Spanish translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-es.cfg/download^French translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-fr.cfg/download^Hungarian translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-hu.cfg/download^Polish translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-pl.cfg/download^Portugese translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-pt.cfg/download^Swedish translation|:fheroes2.cfg:http://sourceforge.net/projects/libsdl-android/files/FreeHeroes2/lang/fheroes2-sv.cfg/download"
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
NeedDepthBuffer=n
SwVideoMode=y
AppUsesMouse=y
AppNeedsTwoButtonMouse=y
AppNeedsArrowKeys=n
@@ -22,8 +23,8 @@ AppTouchscreenKeyboardKeysAmount=0
AppTouchscreenKeyboardKeysAmountAutoFire=0
RedefinedKeysScreenKb="LCTRL M T H E C SPACE C S L"
MultiABI=n
AppVersionCode=225912
AppVersionName="2259.12"
AppVersionCode=226512
AppVersionName="2265.12"
CompiledLibraries="sdl_net sdl_mixer sdl_image sdl_ttf png intl"
CustomBuildScript=n
AppCflags='-finline-functions -O2 -DWITH_ZLIB -DWITH_MIXER -DWITH_XML -DWITH_IMAGE -DWITH_TTF -DWITH_AI=simple'

View File

@@ -1 +1 @@
ballfield
fheroes2

View File

@@ -33,6 +33,7 @@ static char ** argv = NULL;
static int threadedMain(void * unused)
{
SDL_main( argc, argv );
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Application closed, calling exit(0)");
exit(0);
}

View File

@@ -167,6 +167,16 @@ memcpy( &i, p, sizeof(int) ); // The correct way to dereference a non-aligned po
This compiler flags will catch most obvious errors, you may add them to AppCflags var in settings:
-Werror=strict-aliasing -Werror=cast-align -Werror=pointer-arith -Werror=address
The application will automatically get moved to SD-card on Android 2.2 or newer,
(or you can install app2sd for older, but rooted phones),
however the shared libraries have to be stored on the device internal storage,
and that may be not desired for older phones with very little storage.
The script app2sd.sh will re-package your .apk file in such a way that
the shared libraries will not be extracted by Android OS but by application itself,
and it will remove them from internal storage right after starting up,
so you still need that space free, but only temporarily.
How to compile your own application using automake/configure scripts
====================================================================