907 lines
36 KiB
Java
907 lines
36 KiB
Java
/*
|
|
Simple DirectMedia Layer
|
|
Java source code (C) 2009-2014 Sergii Pylypenko
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
package net.sourceforge.clonekeenplus;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.os.Bundle;
|
|
import android.view.MotionEvent;
|
|
import android.view.KeyEvent;
|
|
import android.view.Window;
|
|
import android.view.WindowManager;
|
|
import android.widget.TextView;
|
|
import android.util.Log;
|
|
import java.io.*;
|
|
import android.app.AlertDialog;
|
|
import android.content.DialogInterface;
|
|
import android.os.Environment;
|
|
import android.os.StatFs;
|
|
import java.util.Locale;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.zip.GZIPInputStream;
|
|
import java.util.Collections;
|
|
import android.content.Context;
|
|
import android.content.res.Configuration;
|
|
import android.content.res.Resources;
|
|
import java.lang.String;
|
|
import android.graphics.Matrix;
|
|
import android.graphics.RectF;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
import android.widget.FrameLayout;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.Bitmap;
|
|
import android.widget.TextView;
|
|
import android.widget.EditText;
|
|
import android.widget.ScrollView;
|
|
import android.widget.Button;
|
|
import android.view.View;
|
|
import android.widget.LinearLayout;
|
|
import android.text.Editable;
|
|
import android.text.SpannedString;
|
|
import android.content.Intent;
|
|
import android.app.PendingIntent;
|
|
import android.app.AlarmManager;
|
|
import android.util.DisplayMetrics;
|
|
import android.net.Uri;
|
|
import java.util.concurrent.Semaphore;
|
|
import java.util.Arrays;
|
|
import android.graphics.Color;
|
|
import android.hardware.SensorEventListener;
|
|
import android.hardware.SensorEvent;
|
|
import android.hardware.Sensor;
|
|
import android.widget.Toast;
|
|
import android.content.pm.PackageManager;
|
|
import android.os.Build;
|
|
import android.content.Intent;
|
|
|
|
|
|
// TODO: too much code here, split into multiple files, possibly auto-generated menus?
|
|
class Settings
|
|
{
|
|
static String SettingsFileName = "libsdl-settings.cfg";
|
|
|
|
static boolean settingsLoaded = false;
|
|
static boolean settingsChanged = false;
|
|
static final int SETTINGS_FILE_VERSION = 5;
|
|
|
|
static void Save(final MainActivity p)
|
|
{
|
|
try {
|
|
ObjectOutputStream out = new ObjectOutputStream(p.openFileOutput( SettingsFileName, p.MODE_WORLD_READABLE ));
|
|
out.writeInt(SETTINGS_FILE_VERSION);
|
|
out.writeBoolean(Globals.DownloadToSdcard);
|
|
out.writeBoolean(Globals.PhoneHasArrowKeys);
|
|
out.writeBoolean(false);
|
|
out.writeBoolean(Globals.UseAccelerometerAsArrowKeys);
|
|
out.writeBoolean(Globals.UseTouchscreenKeyboard);
|
|
out.writeInt(Globals.TouchscreenKeyboardSize);
|
|
out.writeInt(Globals.AccelerometerSensitivity);
|
|
out.writeInt(Globals.AccelerometerCenterPos);
|
|
out.writeInt(0);
|
|
out.writeInt(Globals.AudioBufferConfig);
|
|
out.writeInt(Globals.TouchscreenKeyboardTheme);
|
|
out.writeInt(Globals.RightClickMethod);
|
|
out.writeInt(Globals.ShowScreenUnderFinger);
|
|
out.writeInt(Globals.LeftClickMethod);
|
|
out.writeBoolean(Globals.MoveMouseWithJoystick);
|
|
out.writeBoolean(Globals.ClickMouseWithDpad);
|
|
out.writeInt(Globals.ClickScreenPressure);
|
|
out.writeInt(Globals.ClickScreenTouchspotSize);
|
|
out.writeBoolean(Globals.KeepAspectRatio);
|
|
out.writeInt(Globals.MoveMouseWithJoystickSpeed);
|
|
out.writeInt(Globals.MoveMouseWithJoystickAccel);
|
|
out.writeInt(SDL_Keys.JAVA_KEYCODE_LAST);
|
|
for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ )
|
|
{
|
|
out.writeInt(Globals.RemapHwKeycode[i]);
|
|
}
|
|
out.writeInt(Globals.RemapScreenKbKeycode.length);
|
|
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ )
|
|
{
|
|
out.writeInt(Globals.RemapScreenKbKeycode[i]);
|
|
}
|
|
out.writeInt(Globals.ScreenKbControlsShown.length);
|
|
for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ )
|
|
{
|
|
out.writeBoolean(Globals.ScreenKbControlsShown[i]);
|
|
}
|
|
out.writeInt(Globals.TouchscreenKeyboardTransparency);
|
|
out.writeInt(Globals.RemapMultitouchGestureKeycode.length);
|
|
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ )
|
|
{
|
|
out.writeInt(Globals.RemapMultitouchGestureKeycode[i]);
|
|
out.writeBoolean(Globals.MultitouchGesturesUsed[i]);
|
|
}
|
|
out.writeInt(Globals.MultitouchGestureSensitivity);
|
|
for( int i = 0; i < Globals.TouchscreenCalibration.length; i++ )
|
|
out.writeInt(Globals.TouchscreenCalibration[i]);
|
|
out.writeInt(Globals.DataDir.length());
|
|
for( int i = 0; i < Globals.DataDir.length(); i++ )
|
|
out.writeChar(Globals.DataDir.charAt(i));
|
|
out.writeInt(Globals.CommandLine.length());
|
|
for( int i = 0; i < Globals.CommandLine.length(); i++ )
|
|
out.writeChar(Globals.CommandLine.charAt(i));
|
|
out.writeInt(Globals.ScreenKbControlsLayout.length);
|
|
for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ )
|
|
for( int ii = 0; ii < 4; ii++ )
|
|
out.writeInt(Globals.ScreenKbControlsLayout[i][ii]);
|
|
out.writeInt(Globals.LeftClickKey);
|
|
out.writeInt(Globals.RightClickKey);
|
|
out.writeBoolean(Globals.VideoLinearFilter);
|
|
out.writeInt(Globals.LeftClickTimeout);
|
|
out.writeInt(Globals.RightClickTimeout);
|
|
out.writeBoolean(Globals.RelativeMouseMovement);
|
|
out.writeInt(Globals.RelativeMouseMovementSpeed);
|
|
out.writeInt(Globals.RelativeMouseMovementAccel);
|
|
out.writeBoolean(Globals.MultiThreadedVideo);
|
|
|
|
out.writeInt(Globals.OptionalDataDownload.length);
|
|
for(int i = 0; i < Globals.OptionalDataDownload.length; i++)
|
|
out.writeBoolean(Globals.OptionalDataDownload[i]);
|
|
out.writeBoolean(false); // Unused
|
|
out.writeInt(Globals.TouchscreenKeyboardDrawSize);
|
|
out.writeInt(p.getApplicationVersion());
|
|
out.writeFloat(AccelerometerReader.gyro.x1);
|
|
out.writeFloat(AccelerometerReader.gyro.x2);
|
|
out.writeFloat(AccelerometerReader.gyro.xc);
|
|
out.writeFloat(AccelerometerReader.gyro.y1);
|
|
out.writeFloat(AccelerometerReader.gyro.y2);
|
|
out.writeFloat(AccelerometerReader.gyro.yc);
|
|
out.writeFloat(AccelerometerReader.gyro.z1);
|
|
out.writeFloat(AccelerometerReader.gyro.z2);
|
|
out.writeFloat(AccelerometerReader.gyro.zc);
|
|
|
|
out.writeBoolean(Globals.OuyaEmulation);
|
|
out.writeBoolean(Globals.HoverJitterFilter);
|
|
out.writeBoolean(Globals.MoveMouseWithGyroscope);
|
|
out.writeInt(Globals.MoveMouseWithGyroscopeSpeed);
|
|
out.writeBoolean(Globals.FingerHover);
|
|
out.writeBoolean(Globals.FloatingScreenJoystick);
|
|
out.writeBoolean(Globals.GenerateSubframeTouchEvents);
|
|
out.writeInt(Globals.VideoDepthBpp);
|
|
out.writeBoolean(Globals.HorizontalOrientation);
|
|
out.writeBoolean(Globals.ImmersiveMode);
|
|
out.writeBoolean(Globals.AutoDetectOrientation);
|
|
|
|
out.close();
|
|
settingsLoaded = true;
|
|
|
|
} catch( FileNotFoundException e ) {
|
|
} catch( SecurityException e ) {
|
|
} catch ( IOException e ) {};
|
|
}
|
|
|
|
static void Load( final MainActivity p )
|
|
{
|
|
if(settingsLoaded) // Prevent starting twice
|
|
{
|
|
return;
|
|
}
|
|
Log.i("SDL", "libSDL: Settings.Load(): enter");
|
|
nativeInitKeymap();
|
|
if( p.isRunningOnOUYA() )
|
|
nativeSetKeymapKey(KeyEvent.KEYCODE_MENU, nativeGetKeymapKey(KeyEvent.KEYCODE_BACK)); // Ouya does not have Back key, only Menu, so remap Back keycode to Menu
|
|
for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ )
|
|
{
|
|
int sdlKey = nativeGetKeymapKey(i);
|
|
int idx = 0;
|
|
for(int ii = 0; ii < SDL_Keys.values.length; ii++)
|
|
if(SDL_Keys.values[ii] == sdlKey)
|
|
idx = ii;
|
|
Globals.RemapHwKeycode[i] = idx;
|
|
}
|
|
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ )
|
|
{
|
|
int sdlKey = nativeGetKeymapKeyScreenKb(i);
|
|
int idx = 0;
|
|
for(int ii = 0; ii < SDL_Keys.values.length; ii++)
|
|
if(SDL_Keys.values[ii] == sdlKey)
|
|
idx = ii;
|
|
Globals.RemapScreenKbKeycode[i] = idx;
|
|
}
|
|
Globals.ScreenKbControlsShown[0] = (Globals.AppNeedsArrowKeys || Globals.AppUsesJoystick);
|
|
Globals.ScreenKbControlsShown[1] = Globals.AppNeedsTextInput;
|
|
for( int i = 2; i < Globals.ScreenKbControlsShown.length; i++ )
|
|
Globals.ScreenKbControlsShown[i] = ( i - 2 < Globals.AppTouchscreenKeyboardKeysAmount );
|
|
if( Globals.AppUsesSecondJoystick )
|
|
Globals.ScreenKbControlsShown[8] = true;
|
|
if( Globals.AppUsesThirdJoystick )
|
|
Globals.ScreenKbControlsShown[9] = true;
|
|
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ )
|
|
{
|
|
int sdlKey = nativeGetKeymapKeyMultitouchGesture(i);
|
|
int idx = 0;
|
|
for(int ii = 0; ii < SDL_Keys.values.length; ii++)
|
|
if(SDL_Keys.values[ii] == sdlKey)
|
|
idx = ii;
|
|
Globals.RemapMultitouchGestureKeycode[i] = idx;
|
|
}
|
|
for( int i = 0; i < Globals.MultitouchGesturesUsed.length; i++ )
|
|
Globals.MultitouchGesturesUsed[i] = true;
|
|
// Adjust coordinates of on-screen buttons from 800x480
|
|
int displayX = 800;
|
|
int displayY = 480;
|
|
try {
|
|
DisplayMetrics dm = new DisplayMetrics();
|
|
p.getWindowManager().getDefaultDisplay().getMetrics(dm);
|
|
displayX = dm.widthPixels;
|
|
displayY = dm.heightPixels;
|
|
} catch (Exception eeeee) {}
|
|
for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ )
|
|
{
|
|
Globals.ScreenKbControlsLayout[i][0] *= (float)displayX / 800.0f;
|
|
Globals.ScreenKbControlsLayout[i][2] *= (float)displayX / 800.0f;
|
|
Globals.ScreenKbControlsLayout[i][1] *= (float)displayY / 480.0f;
|
|
Globals.ScreenKbControlsLayout[i][3] *= (float)displayY / 480.0f;
|
|
// Make them square
|
|
int wh = Math.min( Globals.ScreenKbControlsLayout[i][2] - Globals.ScreenKbControlsLayout[i][0], Globals.ScreenKbControlsLayout[i][3] - Globals.ScreenKbControlsLayout[i][1] );
|
|
Globals.ScreenKbControlsLayout[i][2] = Globals.ScreenKbControlsLayout[i][0] + wh;
|
|
Globals.ScreenKbControlsLayout[i][3] = Globals.ScreenKbControlsLayout[i][1] + wh;
|
|
}
|
|
|
|
Log.i("SDL", "android.os.Build.MODEL: " + android.os.Build.MODEL);
|
|
if( (android.os.Build.MODEL.equals("GT-N7000") || android.os.Build.MODEL.equals("SGH-I717"))
|
|
&& android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.GINGERBREAD_MR1 )
|
|
{
|
|
// Samsung Galaxy Note generates a keypress when you hover a stylus over the screen, and that messes up OpenTTD dialogs
|
|
// ICS update sends events in a proper way
|
|
Globals.RemapHwKeycode[112] = SDL_1_2_Keycodes.SDLK_UNKNOWN;
|
|
}
|
|
|
|
try {
|
|
ObjectInputStream settingsFile = new ObjectInputStream(new FileInputStream( p.getFilesDir().getAbsolutePath() + "/" + SettingsFileName ));
|
|
if( settingsFile.readInt() != SETTINGS_FILE_VERSION )
|
|
throw new IOException();
|
|
Globals.DownloadToSdcard = settingsFile.readBoolean();
|
|
Globals.PhoneHasArrowKeys = settingsFile.readBoolean();
|
|
settingsFile.readBoolean();
|
|
Globals.UseAccelerometerAsArrowKeys = settingsFile.readBoolean();
|
|
Globals.UseTouchscreenKeyboard = settingsFile.readBoolean();
|
|
Globals.TouchscreenKeyboardSize = settingsFile.readInt();
|
|
Globals.AccelerometerSensitivity = settingsFile.readInt();
|
|
Globals.AccelerometerCenterPos = settingsFile.readInt();
|
|
settingsFile.readInt();
|
|
Globals.AudioBufferConfig = settingsFile.readInt();
|
|
Globals.TouchscreenKeyboardTheme = settingsFile.readInt();
|
|
Globals.RightClickMethod = settingsFile.readInt();
|
|
Globals.ShowScreenUnderFinger = settingsFile.readInt();
|
|
Globals.LeftClickMethod = settingsFile.readInt();
|
|
Globals.MoveMouseWithJoystick = settingsFile.readBoolean();
|
|
Globals.ClickMouseWithDpad = settingsFile.readBoolean();
|
|
Globals.ClickScreenPressure = settingsFile.readInt();
|
|
Globals.ClickScreenTouchspotSize = settingsFile.readInt();
|
|
Globals.KeepAspectRatio = settingsFile.readBoolean();
|
|
Globals.MoveMouseWithJoystickSpeed = settingsFile.readInt();
|
|
Globals.MoveMouseWithJoystickAccel = settingsFile.readInt();
|
|
int readKeys = settingsFile.readInt();
|
|
for( int i = 0; i < readKeys; i++ )
|
|
{
|
|
Globals.RemapHwKeycode[i] = settingsFile.readInt();
|
|
}
|
|
if( settingsFile.readInt() != Globals.RemapScreenKbKeycode.length )
|
|
throw new IOException();
|
|
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ )
|
|
{
|
|
Globals.RemapScreenKbKeycode[i] = settingsFile.readInt();
|
|
}
|
|
if( settingsFile.readInt() != Globals.ScreenKbControlsShown.length )
|
|
throw new IOException();
|
|
for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ )
|
|
{
|
|
Globals.ScreenKbControlsShown[i] = settingsFile.readBoolean();
|
|
}
|
|
Globals.TouchscreenKeyboardTransparency = settingsFile.readInt();
|
|
if( settingsFile.readInt() != Globals.RemapMultitouchGestureKeycode.length )
|
|
throw new IOException();
|
|
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ )
|
|
{
|
|
Globals.RemapMultitouchGestureKeycode[i] = settingsFile.readInt();
|
|
Globals.MultitouchGesturesUsed[i] = settingsFile.readBoolean();
|
|
}
|
|
Globals.MultitouchGestureSensitivity = settingsFile.readInt();
|
|
for( int i = 0; i < Globals.TouchscreenCalibration.length; i++ )
|
|
Globals.TouchscreenCalibration[i] = settingsFile.readInt();
|
|
StringBuilder b = new StringBuilder();
|
|
int len = settingsFile.readInt();
|
|
for( int i = 0; i < len; i++ )
|
|
b.append( settingsFile.readChar() );
|
|
Globals.DataDir = b.toString();
|
|
|
|
b = new StringBuilder();
|
|
len = settingsFile.readInt();
|
|
for( int i = 0; i < len; i++ )
|
|
b.append( settingsFile.readChar() );
|
|
Globals.CommandLine = b.toString();
|
|
|
|
if( settingsFile.readInt() != Globals.ScreenKbControlsLayout.length )
|
|
throw new IOException();
|
|
for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ )
|
|
for( int ii = 0; ii < 4; ii++ )
|
|
Globals.ScreenKbControlsLayout[i][ii] = settingsFile.readInt();
|
|
Globals.LeftClickKey = settingsFile.readInt();
|
|
Globals.RightClickKey = settingsFile.readInt();
|
|
Globals.VideoLinearFilter = settingsFile.readBoolean();
|
|
Globals.LeftClickTimeout = settingsFile.readInt();
|
|
Globals.RightClickTimeout = settingsFile.readInt();
|
|
Globals.RelativeMouseMovement = settingsFile.readBoolean();
|
|
Globals.RelativeMouseMovementSpeed = settingsFile.readInt();
|
|
Globals.RelativeMouseMovementAccel = settingsFile.readInt();
|
|
Globals.MultiThreadedVideo = settingsFile.readBoolean();
|
|
|
|
Globals.OptionalDataDownload = new boolean[settingsFile.readInt()];
|
|
for(int i = 0; i < Globals.OptionalDataDownload.length; i++)
|
|
Globals.OptionalDataDownload[i] = settingsFile.readBoolean();
|
|
settingsFile.readBoolean(); // Unused
|
|
Globals.TouchscreenKeyboardDrawSize = settingsFile.readInt();
|
|
int cfgVersion = settingsFile.readInt();
|
|
AccelerometerReader.gyro.x1 = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.x2 = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.xc = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.y1 = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.y2 = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.yc = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.z1 = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.z2 = settingsFile.readFloat();
|
|
AccelerometerReader.gyro.zc = settingsFile.readFloat();
|
|
|
|
Globals.OuyaEmulation = settingsFile.readBoolean();
|
|
Globals.HoverJitterFilter = settingsFile.readBoolean();
|
|
Globals.MoveMouseWithGyroscope = settingsFile.readBoolean();
|
|
Globals.MoveMouseWithGyroscopeSpeed = settingsFile.readInt();
|
|
Globals.FingerHover = settingsFile.readBoolean();
|
|
Globals.FloatingScreenJoystick = settingsFile.readBoolean();
|
|
Globals.GenerateSubframeTouchEvents = settingsFile.readBoolean();
|
|
Globals.VideoDepthBpp = settingsFile.readInt();
|
|
Globals.HorizontalOrientation = settingsFile.readBoolean();
|
|
Globals.ImmersiveMode = settingsFile.readBoolean();
|
|
Globals.AutoDetectOrientation = settingsFile.readBoolean();
|
|
|
|
settingsLoaded = true;
|
|
|
|
Log.i("SDL", "libSDL: Settings.Load(): loaded settings successfully");
|
|
settingsFile.close();
|
|
|
|
Log.i("SDL", "libSDL: old cfg version " + cfgVersion + ", our version " + p.getApplicationVersion());
|
|
if( cfgVersion != p.getApplicationVersion() )
|
|
{
|
|
DeleteFilesOnUpgrade(p);
|
|
if( Globals.ResetSdlConfigForThisVersion )
|
|
{
|
|
Log.i("SDL", "libSDL: old cfg version " + cfgVersion + ", our version " + p.getApplicationVersion() + " and we need to clean up config file");
|
|
// Delete settings file, and restart the application
|
|
DeleteSdlConfigOnUpgradeAndRestart(p);
|
|
}
|
|
Save(p);
|
|
}
|
|
|
|
return;
|
|
|
|
} catch( FileNotFoundException e ) {
|
|
} catch( SecurityException e ) {
|
|
} catch ( IOException e ) {
|
|
DeleteFilesOnUpgrade(p);
|
|
if( Globals.ResetSdlConfigForThisVersion )
|
|
{
|
|
Log.i("SDL", "libSDL: old cfg version unknown or too old, our version " + p.getApplicationVersion() + " and we need to clean up config file");
|
|
DeleteSdlConfigOnUpgradeAndRestart(p);
|
|
}
|
|
};
|
|
|
|
if( Globals.DataDir.length() == 0 )
|
|
{
|
|
if( !Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) )
|
|
{
|
|
Log.i("SDL", "libSDL: SD card or external storage is not mounted (state " + Environment.getExternalStorageState() + "), switching to the internal storage.");
|
|
Globals.DownloadToSdcard = false;
|
|
}
|
|
if( p.getPackageManager().checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, p.getPackageName()) != PackageManager.PERMISSION_GRANTED )
|
|
{
|
|
Log.i("SDL", "libSDL: We don't have permission to write to SD card, switching to the internal storage.");
|
|
Globals.DownloadToSdcard = false;
|
|
}
|
|
Globals.DataDir = Globals.DownloadToSdcard ?
|
|
SdcardAppPath.getBestPath(p) :
|
|
p.getFilesDir().getAbsolutePath();
|
|
if( Globals.DownloadToSdcard )
|
|
{
|
|
// Check if data already installed into deprecated location at /sdcard/app-data/<package-name>
|
|
String[] fileList = new File(SdcardAppPath.deprecatedPath(p)).list();
|
|
if( fileList != null )
|
|
for( String s: fileList )
|
|
if( s.toUpperCase().startsWith(DataDownloader.DOWNLOAD_FLAG_FILENAME.toUpperCase()) )
|
|
Globals.DataDir = SdcardAppPath.deprecatedPath(p);
|
|
// Also check for pre-Kitkat files location
|
|
fileList = new File(SdcardAppPath.getPath(p)).list();
|
|
if( fileList != null )
|
|
for( String s: fileList )
|
|
if( s.toUpperCase().startsWith(DataDownloader.DOWNLOAD_FLAG_FILENAME.toUpperCase()) )
|
|
Globals.DataDir = SdcardAppPath.getPath(p);
|
|
}
|
|
}
|
|
|
|
Log.i("SDL", "libSDL: Settings.Load(): loading settings failed, running config dialog");
|
|
p.setScreenOrientation();
|
|
p.setUpStatusLabel();
|
|
if( checkRamSize(p) )
|
|
SettingsMenu.showConfig(p, true);
|
|
}
|
|
|
|
// ===============================================================================================
|
|
|
|
public static boolean deleteRecursively(File dir)
|
|
{
|
|
if (dir.isDirectory()) {
|
|
String[] children = dir.list();
|
|
for (int i=0; i<children.length; i++)
|
|
{
|
|
boolean success = deleteRecursively(new File(dir, children[i]));
|
|
if (!success)
|
|
return false;
|
|
}
|
|
}
|
|
return dir.delete();
|
|
}
|
|
public static boolean deleteRecursivelyAndLog(File dir)
|
|
{
|
|
Log.v("SDL", "Deleting old file: " + dir.getAbsolutePath() + " exists " + dir.exists());
|
|
if (dir.isDirectory()) {
|
|
String[] children = dir.list();
|
|
for (int i=0; i<children.length; i++)
|
|
{
|
|
boolean success = deleteRecursively(new File(dir, children[i]));
|
|
if (!success)
|
|
return false;
|
|
}
|
|
}
|
|
return dir.delete();
|
|
}
|
|
public static void DeleteFilesOnUpgrade(final MainActivity p)
|
|
{
|
|
String [] files = Globals.DeleteFilesOnUpgrade.split(" ");
|
|
for(String path: files)
|
|
{
|
|
if( path.equals("") )
|
|
continue;
|
|
|
|
deleteRecursivelyAndLog(new File( SdcardAppPath.getPath(p) + "/" + path ));
|
|
deleteRecursivelyAndLog(new File( p.getFilesDir().getAbsolutePath() + "/" + path ));
|
|
deleteRecursivelyAndLog(new File( SdcardAppPath.deprecatedPath(p) + "/" + path ));
|
|
}
|
|
}
|
|
public static void DeleteSdlConfigOnUpgradeAndRestart(final MainActivity p)
|
|
{
|
|
try {
|
|
ObjectOutputStream out = new ObjectOutputStream(p.openFileOutput( SettingsFileName, p.MODE_WORLD_READABLE ));
|
|
out.writeInt(-1);
|
|
out.close();
|
|
} catch( FileNotFoundException e ) {
|
|
} catch ( IOException e ) { }
|
|
new File( p.getFilesDir() + "/" + SettingsFileName ).delete();
|
|
|
|
Intent intent = new Intent(p, RestartMainActivity.class);
|
|
p.startActivity(intent);
|
|
System.exit(0);
|
|
}
|
|
|
|
// ===============================================================================================
|
|
|
|
static void applyMouseEmulationOptions()
|
|
{
|
|
if( Globals.AppUsesMouse )
|
|
nativeSetMouseUsed( Globals.RightClickMethod,
|
|
Globals.ShowScreenUnderFinger,
|
|
Globals.LeftClickMethod,
|
|
Globals.MoveMouseWithJoystick ? 1 : 0,
|
|
Globals.ClickMouseWithDpad ? 1 : 0,
|
|
Globals.ClickScreenPressure,
|
|
Globals.ClickScreenTouchspotSize,
|
|
Globals.MoveMouseWithJoystickSpeed,
|
|
Globals.MoveMouseWithJoystickAccel,
|
|
Globals.LeftClickKey,
|
|
Globals.RightClickKey,
|
|
Globals.LeftClickTimeout,
|
|
Globals.RightClickTimeout,
|
|
Globals.RelativeMouseMovement ? 1 : 0,
|
|
Globals.RelativeMouseMovementSpeed,
|
|
Globals.RelativeMouseMovementAccel,
|
|
Globals.ShowMouseCursor ? 1 : 0,
|
|
Globals.HoverJitterFilter ? 1 : 0,
|
|
Globals.RightMouseButtonLongPress ? 1 : 0,
|
|
Globals.MoveMouseWithGyroscope ? 1 : 0,
|
|
Globals.MoveMouseWithGyroscopeSpeed,
|
|
Globals.CompatibilityHacksForceScreenUpdateMouseClick ? 1 : 0,
|
|
Globals.ScreenFollowsMouse ? 1 : 0 );
|
|
}
|
|
|
|
static void Apply(MainActivity p)
|
|
{
|
|
setEnvVars(p);
|
|
nativeSetVideoDepth(Globals.VideoDepthBpp, Globals.NeedGles2 ? 1 : 0);
|
|
if(Globals.VideoLinearFilter)
|
|
nativeSetVideoLinearFilter();
|
|
if( Globals.CompatibilityHacksVideo )
|
|
{
|
|
Globals.MultiThreadedVideo = true;
|
|
Globals.SwVideoMode = true;
|
|
nativeSetCompatibilityHacks();
|
|
}
|
|
if( Globals.SwVideoMode )
|
|
nativeSetVideoForceSoftwareMode();
|
|
if( Globals.SwVideoMode && Globals.MultiThreadedVideo )
|
|
nativeSetVideoMultithreaded();
|
|
applyMouseEmulationOptions();
|
|
nativeSetJoystickUsed( Globals.AppUsesThirdJoystick ? 3 : (Globals.AppUsesSecondJoystick ? 2 : (Globals.AppUsesJoystick ? 1 : 0)) );
|
|
if( Globals.AppUsesAccelerometer )
|
|
nativeSetAccelerometerUsed();
|
|
if( Globals.AppUsesMultitouch )
|
|
nativeSetMultitouchUsed();
|
|
nativeSetAccelerometerSettings(Globals.AccelerometerSensitivity, Globals.AccelerometerCenterPos);
|
|
if( Globals.UseTouchscreenKeyboard )
|
|
{
|
|
boolean screenKbReallyUsed = false;
|
|
for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ )
|
|
if( Globals.ScreenKbControlsShown[i] )
|
|
screenKbReallyUsed = true;
|
|
if( p.isRunningOnOUYA() )
|
|
screenKbReallyUsed = false;
|
|
if( screenKbReallyUsed )
|
|
{
|
|
nativeSetTouchscreenKeyboardUsed();
|
|
nativeSetupScreenKeyboard( Globals.TouchscreenKeyboardSize,
|
|
Globals.TouchscreenKeyboardDrawSize,
|
|
Globals.TouchscreenKeyboardTheme,
|
|
Globals.TouchscreenKeyboardTransparency,
|
|
Globals.FloatingScreenJoystick ? 1 : 0 );
|
|
SetupTouchscreenKeyboardGraphics(p);
|
|
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ )
|
|
nativeSetKeymapKeyScreenKb(i, SDL_Keys.values[Globals.RemapScreenKbKeycode[i]]);
|
|
if( Globals.TouchscreenKeyboardSize == Globals.TOUCHSCREEN_KEYBOARD_CUSTOM )
|
|
{
|
|
for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ )
|
|
if( Globals.ScreenKbControlsLayout[i][0] < Globals.ScreenKbControlsLayout[i][2] )
|
|
nativeSetScreenKbKeyLayout( i, Globals.ScreenKbControlsLayout[i][0], Globals.ScreenKbControlsLayout[i][1],
|
|
Globals.ScreenKbControlsLayout[i][2], Globals.ScreenKbControlsLayout[i][3]);
|
|
}
|
|
for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ )
|
|
nativeSetScreenKbKeyUsed(i, Globals.ScreenKbControlsShown[i] ? 1 : 0);
|
|
}
|
|
else
|
|
Globals.UseTouchscreenKeyboard = false;
|
|
}
|
|
|
|
for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ )
|
|
nativeSetKeymapKey(i, SDL_Keys.values[Globals.RemapHwKeycode[i]]);
|
|
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ )
|
|
nativeSetKeymapKeyMultitouchGesture(i, Globals.MultitouchGesturesUsed[i] ? SDL_Keys.values[Globals.RemapMultitouchGestureKeycode[i]] : 0);
|
|
nativeSetMultitouchGestureSensitivity(Globals.MultitouchGestureSensitivity);
|
|
if( Globals.TouchscreenCalibration[2] > Globals.TouchscreenCalibration[0] )
|
|
nativeSetTouchscreenCalibration(Globals.TouchscreenCalibration[0], Globals.TouchscreenCalibration[1],
|
|
Globals.TouchscreenCalibration[2], Globals.TouchscreenCalibration[3]);
|
|
}
|
|
|
|
static void setEnvVars(MainActivity p)
|
|
{
|
|
String lang = new String(Locale.getDefault().getLanguage());
|
|
if( Locale.getDefault().getCountry().length() > 0 )
|
|
lang = lang + "_" + Locale.getDefault().getCountry();
|
|
Log.i("SDL", "libSDL: setting envvar LANGUAGE to '" + lang + "'");
|
|
nativeSetEnv( "LANG", lang );
|
|
nativeSetEnv( "LANGUAGE", lang );
|
|
// TODO: get current user name and set envvar USER, the API is not availalbe on Android 1.6 so I don't bother with this
|
|
nativeSetEnv( "APPDIR", p.getFilesDir().getAbsolutePath() );
|
|
nativeSetEnv( "SECURE_STORAGE_DIR", p.getFilesDir().getAbsolutePath() );
|
|
nativeSetEnv( "DATADIR", Globals.DataDir );
|
|
nativeSetEnv( "UNSECURE_STORAGE_DIR", Globals.DataDir );
|
|
SdcardAppPath.setEnv(p);
|
|
nativeSetEnv( "HOME", Globals.DataDir );
|
|
nativeSetEnv( "SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath() );
|
|
nativeSetEnv( "ANDROID_VERSION", String.valueOf(android.os.Build.VERSION.SDK_INT) );
|
|
nativeSetEnv( "ANDROID_PACKAGE_NAME", p.getPackageName() );
|
|
try {
|
|
nativeSetEnv( "ANDROID_APP_NAME", p.getString(p.getApplicationInfo().labelRes) );
|
|
} catch (Exception eeeeee) {}
|
|
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO )
|
|
nativeSetEnv( "ANDROID_PACKAGE_PATH", p.getPackageCodePath() );
|
|
Log.d("SDL", "libSDL: Is running on OUYA: " + p.isRunningOnOUYA());
|
|
if( p.isRunningOnOUYA() )
|
|
nativeSetEnv( "OUYA", "1" );
|
|
if (p.getIntent().getStringExtra(RestartMainActivity.SDL_RESTART_PARAMS) != null)
|
|
nativeSetEnv( RestartMainActivity.SDL_RESTART_PARAMS, p.getIntent().getStringExtra(RestartMainActivity.SDL_RESTART_PARAMS) );
|
|
try {
|
|
DisplayMetrics dm = new DisplayMetrics();
|
|
p.getWindowManager().getDefaultDisplay().getMetrics(dm);
|
|
float xx = dm.widthPixels/dm.xdpi;
|
|
float yy = dm.heightPixels/dm.ydpi;
|
|
float x = Math.max(xx, yy);
|
|
float y = Math.min(xx, yy);
|
|
float displayInches = (float)Math.sqrt( x*x + y*y );
|
|
nativeSetEnv( "DISPLAY_SIZE", String.valueOf(displayInches) );
|
|
nativeSetEnv( "DISPLAY_SIZE_MM", String.valueOf((int)(displayInches*25.4f)) );
|
|
nativeSetEnv( "DISPLAY_WIDTH", String.valueOf(x) );
|
|
nativeSetEnv( "DISPLAY_HEIGHT", String.valueOf(y) );
|
|
nativeSetEnv( "DISPLAY_WIDTH_MM", String.valueOf((int)(x*25.4f)) );
|
|
nativeSetEnv( "DISPLAY_HEIGHT_MM", String.valueOf((int)(y*25.4f)) );
|
|
nativeSetEnv( "DISPLAY_RESOLUTION_WIDTH", String.valueOf(Math.max(dm.widthPixels, dm.heightPixels)) );
|
|
nativeSetEnv( "DISPLAY_RESOLUTION_HEIGHT", String.valueOf(Math.min(dm.widthPixels, dm.heightPixels)) );
|
|
} catch (Exception eeeee) {}
|
|
}
|
|
|
|
static byte [] loadRaw(Activity p, int res)
|
|
{
|
|
byte [] buf = new byte[65536 * 2];
|
|
byte [] a = new byte[1048576 * 5]; // We need 5Mb buffer for Keen theme, and this Java code is inefficient
|
|
int written = 0;
|
|
try{
|
|
InputStream is = new GZIPInputStream(p.getResources().openRawResource(res));
|
|
int readed = 0;
|
|
while( (readed = is.read(buf)) >= 0 )
|
|
{
|
|
if( written + readed > a.length )
|
|
{
|
|
byte [] b = new byte [written + readed];
|
|
System.arraycopy(a, 0, b, 0, written);
|
|
a = b;
|
|
}
|
|
System.arraycopy(buf, 0, a, written, readed);
|
|
written += readed;
|
|
}
|
|
} catch(Exception e) {};
|
|
byte [] b = new byte [written];
|
|
System.arraycopy(a, 0, b, 0, written);
|
|
return b;
|
|
}
|
|
|
|
static void SetupTouchscreenKeyboardGraphics(Activity p)
|
|
{
|
|
if( Globals.UseTouchscreenKeyboard )
|
|
{
|
|
if(Globals.TouchscreenKeyboardTheme < 0)
|
|
Globals.TouchscreenKeyboardTheme = 0;
|
|
if(Globals.TouchscreenKeyboardTheme > 9)
|
|
Globals.TouchscreenKeyboardTheme = 9;
|
|
|
|
if( Globals.TouchscreenKeyboardTheme == 0 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.ultimatedroid));
|
|
if( Globals.TouchscreenKeyboardTheme == 1 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.simpletheme));
|
|
if( Globals.TouchscreenKeyboardTheme == 2 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.sun));
|
|
if( Globals.TouchscreenKeyboardTheme == 3 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.keen));
|
|
if( Globals.TouchscreenKeyboardTheme == 4 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.retro));
|
|
if( Globals.TouchscreenKeyboardTheme == 5 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.gba));
|
|
if( Globals.TouchscreenKeyboardTheme == 6 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.psx));
|
|
if( Globals.TouchscreenKeyboardTheme == 7 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.snes));
|
|
if( Globals.TouchscreenKeyboardTheme == 8 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.dualshock));
|
|
if( Globals.TouchscreenKeyboardTheme == 9 )
|
|
nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.n64));
|
|
}
|
|
}
|
|
|
|
abstract static class SdcardAppPath
|
|
{
|
|
private static SdcardAppPath get()
|
|
{
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
|
|
return Kitkat.Holder.sInstance;
|
|
else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO)
|
|
return Froyo.Holder.sInstance;
|
|
else
|
|
return Dummy.Holder.sInstance;
|
|
}
|
|
public abstract String path(final Context p);
|
|
private void setEnvInternal(final Context p)
|
|
{
|
|
nativeSetEnv( "UNSECURE_STORAGE_DIR_0", Globals.DataDir );
|
|
}
|
|
public static void setEnv(final Context p)
|
|
{
|
|
get().setEnvInternal(p);
|
|
}
|
|
public String bestPath(final Context p)
|
|
{
|
|
return path(p);
|
|
};
|
|
public static String deprecatedPath(final Context p)
|
|
{
|
|
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/app-data/" + p.getPackageName();
|
|
}
|
|
public static String getPath(final Context p)
|
|
{
|
|
try {
|
|
return get().path(p);
|
|
} catch(Exception e) { }
|
|
return Dummy.Holder.sInstance.path(p);
|
|
}
|
|
public static String getBestPath(final Context p)
|
|
{
|
|
try {
|
|
return get().bestPath(p);
|
|
} catch(Exception e) { }
|
|
return Dummy.Holder.sInstance.path(p);
|
|
}
|
|
|
|
private static class Froyo extends SdcardAppPath
|
|
{
|
|
private static class Holder
|
|
{
|
|
private static final Froyo sInstance = new Froyo();
|
|
}
|
|
public String path(final Context p)
|
|
{
|
|
return p.getExternalFilesDir(null).getAbsolutePath();
|
|
}
|
|
}
|
|
private static class Kitkat extends Froyo
|
|
{
|
|
private static class Holder
|
|
{
|
|
private static final Kitkat sInstance = new Kitkat();
|
|
}
|
|
public String bestPath(final Context p)
|
|
{
|
|
File[] paths = p.getExternalFilesDirs(null);
|
|
String ret = path(p);
|
|
long maxSize = -1;
|
|
for( File path: paths )
|
|
{
|
|
if( path == null )
|
|
continue;
|
|
StatFs stat = new StatFs(path.getPath());
|
|
long size = (long)stat.getAvailableBlocks() * stat.getBlockSize() / 1024 / 1024;
|
|
if( size > maxSize )
|
|
{
|
|
maxSize = size;
|
|
ret = path.getAbsolutePath();
|
|
}
|
|
}
|
|
return ret;
|
|
};
|
|
public void setEnvInternal(final Context p)
|
|
{
|
|
File[] paths = p.getExternalFilesDirs(null);
|
|
int index = 0;
|
|
for( File path: paths )
|
|
{
|
|
if( path == null )
|
|
continue;
|
|
if( !path.exists() )
|
|
path.mkdirs();
|
|
nativeSetEnv( "UNSECURE_STORAGE_DIR_" + index, path.getAbsolutePath() );
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
private static class Dummy extends SdcardAppPath
|
|
{
|
|
private static class Holder
|
|
{
|
|
private static final Dummy sInstance = new Dummy();
|
|
}
|
|
public String path(final Context p)
|
|
{
|
|
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + p.getPackageName() + "/files";
|
|
}
|
|
}
|
|
}
|
|
|
|
static boolean checkRamSize(final MainActivity p)
|
|
{
|
|
try {
|
|
BufferedReader reader = new BufferedReader(new FileReader("/proc/meminfo"));
|
|
String line = null;
|
|
while( ( line = reader.readLine() ) != null )
|
|
{
|
|
if( line.indexOf("MemTotal:") == 0 )
|
|
{
|
|
String[] fields = line.split("[ \t]+");
|
|
Long size = Long.parseLong(fields[1]);
|
|
Log.i("SDL", "Device RAM size: " + size / 1024 + " Mb, required minimum RAM: " + Globals.AppMinimumRAM + " Mb" );
|
|
if( size / 1024 < Globals.AppMinimumRAM )
|
|
{
|
|
settingsChanged = true;
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(p);
|
|
builder.setTitle(R.string.not_enough_ram);
|
|
builder.setMessage(p.getResources().getString( R.string.not_enough_ram_size, Globals.AppMinimumRAM, (int)(size / 1024)) );
|
|
builder.setPositiveButton(p.getResources().getString(R.string.ok), new DialogInterface.OnClickListener()
|
|
{
|
|
public void onClick(DialogInterface dialog, int item)
|
|
{
|
|
p.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + p.getPackageName())));
|
|
System.exit(0);
|
|
}
|
|
});
|
|
builder.setNegativeButton(p.getResources().getString(R.string.ignore), new DialogInterface.OnClickListener()
|
|
{
|
|
public void onClick(DialogInterface dialog, int item)
|
|
{
|
|
SettingsMenu.showConfig(p, true);
|
|
return;
|
|
}
|
|
});
|
|
builder.setOnCancelListener(new DialogInterface.OnCancelListener()
|
|
{
|
|
public void onCancel(DialogInterface dialog)
|
|
{
|
|
p.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + p.getPackageName())));
|
|
System.exit(0);
|
|
}
|
|
});
|
|
final AlertDialog alert = builder.create();
|
|
alert.setOwnerActivity(p);
|
|
alert.show();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
} catch ( Exception e ) {
|
|
Log.i("SDL", "Error: cannot parse /proc/meminfo: " + e.toString());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static native void nativeSetAccelerometerSettings(int sensitivity, int centerPos);
|
|
private static native void nativeSetMouseUsed(int RightClickMethod, int ShowScreenUnderFinger, int LeftClickMethod,
|
|
int MoveMouseWithJoystick, int ClickMouseWithDpad, int MaxForce, int MaxRadius,
|
|
int MoveMouseWithJoystickSpeed, int MoveMouseWithJoystickAccel,
|
|
int leftClickKeycode, int rightClickKeycode,
|
|
int leftClickTimeout, int rightClickTimeout,
|
|
int relativeMovement, int relativeMovementSpeed,
|
|
int relativeMovementAccel, int showMouseCursor,
|
|
int HoverJitterFilter, int RightMouseButtonLongPress,
|
|
int MoveMouseWithGyroscope, int MoveMouseWithGyroscopeSpeed,
|
|
int ForceScreenUpdateMouseClick, int ScreenFollowsMouse);
|
|
private static native void nativeSetJoystickUsed(int amount);
|
|
private static native void nativeSetAccelerometerUsed();
|
|
private static native void nativeSetMultitouchUsed();
|
|
private static native void nativeSetTouchscreenKeyboardUsed();
|
|
private static native void nativeSetVideoLinearFilter();
|
|
private static native void nativeSetVideoDepth(int bpp, int gles2);
|
|
private static native void nativeSetCompatibilityHacks();
|
|
private static native void nativeSetVideoMultithreaded();
|
|
private static native void nativeSetVideoForceSoftwareMode();
|
|
private static native void nativeSetupScreenKeyboard(int size, int drawsize, int theme, int transparency, int floatingScreenJoystick);
|
|
private static native void nativeSetupScreenKeyboardButtons(byte[] img);
|
|
private static native void nativeInitKeymap();
|
|
private static native int nativeGetKeymapKey(int key);
|
|
private static native void nativeSetKeymapKey(int javakey, int key);
|
|
private static native int nativeGetKeymapKeyScreenKb(int keynum);
|
|
private static native void nativeSetKeymapKeyScreenKb(int keynum, int key);
|
|
private static native void nativeSetScreenKbKeyUsed(int keynum, int used);
|
|
private static native void nativeSetScreenKbKeyLayout(int keynum, int x1, int y1, int x2, int y2);
|
|
private static native int nativeGetKeymapKeyMultitouchGesture(int keynum);
|
|
private static native void nativeSetKeymapKeyMultitouchGesture(int keynum, int key);
|
|
private static native void nativeSetMultitouchGestureSensitivity(int sensitivity);
|
|
private static native void nativeSetTouchscreenCalibration(int x1, int y1, int x2, int y2);
|
|
public static native void nativeSetEnv(final String name, final String value);
|
|
public static native int nativeChmod(final String name, int mode);
|
|
public static native void nativeChdir(final String dir);
|
|
}
|