Skip to content

Commit

Permalink
app2sd support for shared libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
pelya committed Feb 18, 2011
1 parent 881ebab commit 4f3665e
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 30 deletions.
6 changes: 3 additions & 3 deletions ChangeAppSettings.sh
Expand Up @@ -488,15 +488,15 @@ 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
for lib1 in $StaticLibraries; do
if [ "$lib" = "$lib1" ]; then process=false; fi
done
if $process; then
LibrariesToLoad="$LibrariesToLoad System.loadLibrary(\\\"$lib\\\");"
LibrariesToLoad="$LibrariesToLoad, \\\"$lib\\\""
fi
done

Expand Down Expand Up @@ -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

Expand Down
35 changes: 35 additions & 0 deletions app2sd.sh
@@ -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
6 changes: 2 additions & 4 deletions project/java/Globals.java
Expand Up @@ -9,6 +9,8 @@
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
Expand Down Expand Up @@ -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"); };
}
134 changes: 118 additions & 16 deletions project/java/MainActivity.java
Expand Up @@ -24,6 +24,16 @@
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 {
Expand Down Expand Up @@ -81,7 +91,7 @@ public void onClick(View v)
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);
Expand Down Expand Up @@ -223,19 +233,13 @@ public void hideScreenKeyboard()
{
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);
Expand All @@ -255,12 +259,19 @@ class myKeyListener implements OnKeyListener
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 );
Expand Down Expand Up @@ -376,13 +387,104 @@ public void hideTaskbarNotification()
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;

Expand Down
24 changes: 22 additions & 2 deletions project/java/Video.java
Expand Up @@ -18,6 +18,7 @@
import android.view.Window;
import android.view.WindowManager;
import android.os.Environment;
import java.io.File;

import android.widget.TextView;
import java.lang.Thread;
Expand Down Expand Up @@ -205,8 +206,27 @@ public void onDrawFrame(GL10 gl) {
// 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
Expand Down
9 changes: 5 additions & 4 deletions project/jni/application/fheroes2/AndroidAppSettings.cfg
@@ -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
Expand All @@ -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'
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion project/jni/application/src
1 change: 1 addition & 0 deletions project/jni/sdl_main/sdl_main.c
Expand Up @@ -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);
}

Expand Down
10 changes: 10 additions & 0 deletions readme.txt
Expand Up @@ -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
====================================================================

Expand Down

0 comments on commit 4f3665e

Please sign in to comment.