mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Move the Android Java wrapper code in here.
This commit is contained in:
parent
cb7e3e62e7
commit
0983adb052
14 changed files with 578 additions and 0 deletions
8
android/.classpath
Normal file
8
android/.classpath
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?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 kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
2
android/.gitignore
vendored
Normal file
2
android/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
gen
|
||||
bin
|
33
android/.project
Normal file
33
android/.project
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>libnative</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>
|
14
android/AndroidManifest.xml
Normal file
14
android/AndroidManifest.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.turboviking.libnative"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name" >
|
||||
</application>
|
||||
|
||||
</manifest>
|
20
android/proguard-project.txt
Normal file
20
android/proguard-project.txt
Normal 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 *;
|
||||
#}
|
15
android/project.properties
Normal file
15
android/project.properties
Normal file
|
@ -0,0 +1,15 @@
|
|||
# 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-8
|
||||
android.library=true
|
BIN
android/res/drawable-hdpi/ic_launcher.png
Normal file
BIN
android/res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
BIN
android/res/drawable-ldpi/ic_launcher.png
Normal file
BIN
android/res/drawable-ldpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
android/res/drawable-mdpi/ic_launcher.png
Normal file
BIN
android/res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
android/res/drawable-xhdpi/ic_launcher.png
Normal file
BIN
android/res/drawable-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
12
android/res/layout/main.xml
Normal file
12
android/res/layout/main.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello" />
|
||||
|
||||
</LinearLayout>
|
7
android/res/values/strings.xml
Normal file
7
android/res/values/strings.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="hello">Hello World!</string>
|
||||
<string name="app_name">libnative</string>
|
||||
|
||||
</resources>
|
449
android/src/com/turboviking/libnative/NativeActivity.java
Normal file
449
android/src/com/turboviking/libnative/NativeActivity.java
Normal file
|
@ -0,0 +1,449 @@
|
|||
package com.turboviking.libnative;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ConfigurationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioTrack;
|
||||
import android.net.Uri;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
class NativeRenderer implements GLSurfaceView.Renderer {
|
||||
private static String TAG = "RollerballRenderer";
|
||||
NativeActivity mActivity;
|
||||
|
||||
NativeRenderer(NativeActivity act) {
|
||||
mActivity = act;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
|
||||
Log.i(TAG, "onSurfaceCreated");
|
||||
displayInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 unused /*use GLES20*/) {
|
||||
displayRender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(GL10 unused, int width, int height) {
|
||||
Log.i(TAG, "onSurfaceChanged");
|
||||
displayResize(width, height);
|
||||
}
|
||||
|
||||
|
||||
// NATIVE METHODS
|
||||
|
||||
public native void displayInit();
|
||||
// Note: This also means "device lost" and you should reload
|
||||
// all buffered objects.
|
||||
public native void displayResize(int w, int h);
|
||||
public native void displayRender();
|
||||
|
||||
// called by the C++ code through JNI. Dispatch anything we can't directly handle
|
||||
// on the gfx thread to the UI thread.
|
||||
public void postCommand(String command, String parameter) {
|
||||
final String cmd = command;
|
||||
final String param = parameter;
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NativeRenderer.this.mActivity.processCommand(cmd, param);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Touch- and sensor-enabled GLSurfaceView.
|
||||
class NativeGLView extends GLSurfaceView implements SensorEventListener {
|
||||
private static String TAG = "NativeGLView";
|
||||
private SensorManager mSensorManager;
|
||||
private Sensor mAccelerometer;
|
||||
|
||||
public NativeGLView(NativeActivity activity) {
|
||||
super(activity);
|
||||
setEGLContextClientVersion(2);
|
||||
// setEGLConfigChooser(5, 5, 5, 0, 16, 0);
|
||||
// setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
|
||||
mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE);
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
}
|
||||
|
||||
// This needs fleshing out. A lot.
|
||||
// Going to want multitouch eventually.
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
int code = 0;
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
code = 1;
|
||||
} else if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
code = 2;
|
||||
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
code = 3;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
NativeApp.touch((int)event.getRawX(), (int)event.getRawY(), code);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sensor management
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int arg1) {
|
||||
Log.i(TAG, "onAccuracyChanged");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
|
||||
return;
|
||||
}
|
||||
// Can also look at event.timestamp for accuracy magic
|
||||
NativeApp.accelerometer(event.values[0], event.values[1], event.values[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mSensorManager.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class NativeAudioPlayer {
|
||||
private String TAG = "NativeAudioPlayer";
|
||||
private Thread thread;
|
||||
private boolean playing_;
|
||||
|
||||
// Calling stop() is allowed at any time, whether stopped or not.
|
||||
// If playing, blocks until not.
|
||||
public synchronized void stop() {
|
||||
if (thread != null) {
|
||||
waitUntilDone();
|
||||
} else {
|
||||
Log.e(TAG, "Was already stopped");
|
||||
}
|
||||
}
|
||||
|
||||
// If not playing, make sure we're playing.
|
||||
public synchronized void play() {
|
||||
if (thread == null) {
|
||||
playStreaming();
|
||||
} else {
|
||||
Log.e(TAG, "Was already playing");
|
||||
}
|
||||
}
|
||||
|
||||
private void playStreaming() {
|
||||
playing_ = true;
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
playThread();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void waitUntilDone() {
|
||||
if (!playing_) {
|
||||
Log.i(TAG, "not playing.");
|
||||
}
|
||||
try {
|
||||
playing_ = false;
|
||||
Log.e(TAG, "waitUntilDone: Joining audio thread.");
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "INterrupted!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
thread = null;
|
||||
Log.i(TAG, "Finished waitUntilDone");
|
||||
}
|
||||
|
||||
private void playThread() {
|
||||
try {
|
||||
Log.i(TAG, "Thread started.");
|
||||
// Get the smallest possible buffer size (which is annoyingly huge).
|
||||
int buffer_size_bytes = AudioTrack.getMinBufferSize(
|
||||
44100,
|
||||
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
|
||||
AudioFormat.ENCODING_PCM_16BIT);
|
||||
|
||||
// Round buffer_size_bytes up to an even multiple of 128 for convenience.
|
||||
buffer_size_bytes = (buffer_size_bytes + 127) & ~127;
|
||||
|
||||
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
|
||||
44100,
|
||||
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
|
||||
AudioFormat.ENCODING_PCM_16BIT,
|
||||
buffer_size_bytes,
|
||||
AudioTrack.MODE_STREAM);
|
||||
|
||||
int buffer_size = buffer_size_bytes / 2;
|
||||
short [] buffer = new short[buffer_size];
|
||||
audioTrack.play();
|
||||
Log.i(TAG, "Playing... minBuffersize = " + buffer_size);
|
||||
while (playing_) {
|
||||
NativeApp.audioRender(buffer);
|
||||
audioTrack.write(buffer, 0, buffer_size);
|
||||
}
|
||||
audioTrack.stop();
|
||||
audioTrack.release();
|
||||
Log.i(TAG, "Stopped playing.");
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "Playback Failed");
|
||||
t.printStackTrace();
|
||||
Log.e(TAG, t.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Installation {
|
||||
private static String sID = null;
|
||||
private static final String INSTALLATION = "INSTALLATION";
|
||||
|
||||
public synchronized static String id(Context context) {
|
||||
if (sID == null) {
|
||||
File installation = new File(context.getFilesDir(), INSTALLATION);
|
||||
try {
|
||||
if (!installation.exists())
|
||||
writeInstallationFile(installation);
|
||||
sID = readInstallationFile(installation);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return sID;
|
||||
}
|
||||
|
||||
private static String readInstallationFile(File installation) throws IOException {
|
||||
RandomAccessFile f = new RandomAccessFile(installation, "r");
|
||||
byte[] bytes = new byte[(int) f.length()];
|
||||
f.readFully(bytes);
|
||||
f.close();
|
||||
return new String(bytes);
|
||||
}
|
||||
|
||||
private static void writeInstallationFile(File installation) throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(installation);
|
||||
String id = UUID.randomUUID().toString();
|
||||
out.write(id.getBytes());
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class NativeActivity extends Activity {
|
||||
// Remember to loadLibrary your JNI .so in a static {} block
|
||||
|
||||
// Adjust these as necessary
|
||||
private static String TAG = "NativeActivity";
|
||||
String packageName = "com.turboviking.rollerball";
|
||||
|
||||
// Graphics and audio interfaces
|
||||
private GLSurfaceView mGLSurfaceView;
|
||||
private NativeAudioPlayer audioPlayer;
|
||||
|
||||
|
||||
public static String runCommand;
|
||||
public static String commandParameter;
|
||||
|
||||
public static String installID;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.i(TAG, "onCreate");
|
||||
installID = Installation.id(this);
|
||||
// Get system information
|
||||
ApplicationInfo appInfo = null;
|
||||
PackageManager packMgmr = getPackageManager();
|
||||
try {
|
||||
appInfo = packMgmr.getApplicationInfo(packageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Unable to locate assets, aborting...");
|
||||
}
|
||||
File sdcard = Environment.getExternalStorageDirectory();
|
||||
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
int scrPixelFormat = display.getPixelFormat();
|
||||
int scrWidth = display.getWidth();
|
||||
int scrHeight = display.getHeight();
|
||||
float scrRefreshRate = (float)display.getRefreshRate();
|
||||
String externalStorageDir = sdcard.getAbsolutePath();
|
||||
String dataDir = this.getFilesDir().getAbsolutePath();
|
||||
String apkFilePath = appInfo.sourceDir;
|
||||
NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, installID);
|
||||
|
||||
// Keep the screen bright - very annoying if it goes dark when tilting away
|
||||
Window window = this.getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat);
|
||||
|
||||
// Initialize Graphics
|
||||
if (!detectOpenGLES20()) {
|
||||
throw new RuntimeException("Application requires OpenGL ES 2.0.");
|
||||
} else {
|
||||
Log.i(TAG, "OpenGL ES 2.0 detected.");
|
||||
}
|
||||
|
||||
mGLSurfaceView = new NativeGLView(this);
|
||||
mGLSurfaceView.setRenderer(new NativeRenderer(this));
|
||||
setContentView(mGLSurfaceView);
|
||||
audioPlayer = new NativeAudioPlayer();
|
||||
}
|
||||
|
||||
private boolean detectOpenGLES20() {
|
||||
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
ConfigurationInfo info = am.getDeviceConfigurationInfo();
|
||||
return info.reqGlEsVersion >= 0x20000;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
Log.i(TAG, "onPause");
|
||||
if (audioPlayer != null) {
|
||||
audioPlayer.stop();
|
||||
}
|
||||
mGLSurfaceView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Log.i(TAG, "onResume");
|
||||
mGLSurfaceView.onResume();
|
||||
if (audioPlayer != null) {
|
||||
audioPlayer.play();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Log.i(TAG, "onStop");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.e(TAG, "onDestroy");
|
||||
NativeApp.shutdown();
|
||||
audioPlayer = null;
|
||||
mGLSurfaceView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
// Eat these keys, to avoid accidental exits / other screwups.
|
||||
// Maybe there's even more we need to eat on tablets?
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
NativeApp.keyDown(1);
|
||||
return true;
|
||||
}
|
||||
else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
NativeApp.keyDown(2);
|
||||
return true;
|
||||
}
|
||||
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||
NativeApp.keyDown(3);
|
||||
return true;
|
||||
}
|
||||
// Don't process any other keys.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
// Eat these keys, to avoid accidental exits / other screwups.
|
||||
// Maybe there's even more we need to eat on tablets?
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
NativeApp.keyUp(1);
|
||||
return true;
|
||||
}
|
||||
else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
// Menu should be ignored from android 3 forwards
|
||||
NativeApp.keyUp(2);
|
||||
return true;
|
||||
}
|
||||
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||
// Search probably should also be ignored.
|
||||
NativeApp.keyUp(3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent destroying and recreating the main activity when the device rotates etc,
|
||||
// since this would stop the sound.
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
// Ignore orientation change
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
public void processCommand(String command, String params) {
|
||||
if (command.equals("launchBrowser")) {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params));
|
||||
startActivity(i);
|
||||
} else if (command.equals("launchEmail")) {
|
||||
Intent send = new Intent(Intent.ACTION_SENDTO);
|
||||
String uriText;
|
||||
uriText = "mailto:email@gmail.com" +
|
||||
"?subject=Rollfish is..." +
|
||||
"&body=great! Or?";
|
||||
uriText = uriText.replace(" ", "%20");
|
||||
Uri uri = Uri.parse(uriText);
|
||||
send.setData(uri);
|
||||
startActivity(Intent.createChooser(send, "E-mail Henrik!"));
|
||||
} else if (command.equals("launchMarket")) {
|
||||
// http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app
|
||||
// http://developer.android.com/guide/publishing/publishing.html#marketintent
|
||||
} else if (command.equals("toast")) {
|
||||
Toast toast = Toast.makeText(this, params, 2000);
|
||||
toast.show();
|
||||
} else {
|
||||
Log.e(TAG, "Unsupported command " + command + " , param: " + params);
|
||||
}
|
||||
}
|
||||
}
|
18
android/src/com/turboviking/libnative/NativeApp.java
Normal file
18
android/src/com/turboviking/libnative/NativeApp.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package com.turboviking.libnative;
|
||||
|
||||
public class NativeApp {
|
||||
public static native void init(
|
||||
int xxres, int yyres, String apkPath,
|
||||
String dataDir, String externalDir, String installID);
|
||||
public static native void shutdown();
|
||||
|
||||
public static native void keyDown(int key);
|
||||
public static native void keyUp(int key);
|
||||
|
||||
// will only be called between init() and shutdown()
|
||||
public static native void audioRender(short [] buffer);
|
||||
|
||||
// Sensor/input data. These are asynchronous, beware!
|
||||
public static native void touch(int x, int y, int data);
|
||||
public static native void accelerometer(float x, float y, float z);
|
||||
}
|
Loading…
Add table
Reference in a new issue