1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-06 12:20:30 +00:00

Renamed godot domain from com.android.godot (which was incorrect) to org.godotengine.godot

This commit is contained in:
Juan Linietsky
2016-01-08 17:53:00 -03:00
parent 401622cc22
commit 40ba22631b
29 changed files with 106 additions and 106 deletions

View File

@@ -1,80 +0,0 @@
/*************************************************************************/
/* Dictionary.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import java.util.HashMap;
import java.util.Set;
public class Dictionary extends HashMap<String, Object> {
protected String[] keys_cache;
public String[] get_keys() {
String[] ret = new String[size()];
int i=0;
Set<String> keys = keySet();
for (String key : keys) {
ret[i] = key;
i++;
};
return ret;
};
public Object[] get_values() {
Object[] ret = new Object[size()];
int i=0;
Set<String> keys = keySet();
for (String key : keys) {
ret[i] = get(key);
i++;
};
return ret;
};
public void set_keys(String[] keys) {
keys_cache = keys;
};
public void set_values(Object[] vals) {
int i=0;
for (String key : keys_cache) {
put(key, vals[i]);
i++;
};
keys_cache = null;
};
};

View File

@@ -1,925 +0,0 @@
/*************************************************************************/
/* Godot.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import android.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.view.ViewGroup.LayoutParams;
import android.app.*;
import android.content.*;
import android.content.SharedPreferences.Editor;
import android.view.*;
import android.view.inputmethod.InputMethodManager;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.media.MediaPlayer;
import java.lang.reflect.Method;
import java.util.List;
import java.util.ArrayList;
import com.android.godot.payments.PaymentsManager;
import java.io.IOException;
import android.provider.Settings.Secure;
import android.widget.FrameLayout;
import com.android.godot.input.*;
import java.io.InputStream;
import javax.microedition.khronos.opengles.GL10;
import java.security.MessageDigest;
import java.io.File;
import java.io.FileInputStream;
import java.util.LinkedList;
import com.google.android.vending.expansion.downloader.Constants;
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
import com.google.android.vending.expansion.downloader.DownloaderServiceMarshaller;
import com.google.android.vending.expansion.downloader.Helpers;
import com.google.android.vending.expansion.downloader.IDownloaderClient;
import com.google.android.vending.expansion.downloader.IDownloaderService;
import com.google.android.vending.expansion.downloader.IStub;
import android.os.Bundle;
import android.os.Messenger;
import android.os.SystemClock;
public class Godot extends Activity implements SensorEventListener, IDownloaderClient
{
static final int MAX_SINGLETONS = 64;
private IStub mDownloaderClientStub;
private IDownloaderService mRemoteService;
private TextView mStatusText;
private TextView mProgressFraction;
private TextView mProgressPercent;
private TextView mAverageSpeed;
private TextView mTimeRemaining;
private ProgressBar mPB;
private View mDashboard;
private View mCellMessage;
private Button mPauseButton;
private Button mWiFiSettingsButton;
private boolean use_32_bits=false;
private boolean use_immersive=false;
private boolean mStatePaused;
private int mState;
private void setState(int newState) {
if (mState != newState) {
mState = newState;
mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
}
}
private void setButtonPausedState(boolean paused) {
mStatePaused = paused;
int stringResourceID = paused ? com.godot.game.R.string.text_button_resume :
com.godot.game.R.string.text_button_pause;
mPauseButton.setText(stringResourceID);
}
static public class SingletonBase {
protected void registerClass(String p_name, String[] p_methods) {
GodotLib.singleton(p_name,this);
Class clazz = getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
boolean found=false;
Log.d("XXX","METHOD: %s\n" + method.getName());
for (String s : p_methods) {
Log.d("XXX", "METHOD CMP WITH: %s\n" + s);
if (s.equals(method.getName())) {
found=true;
Log.d("XXX","METHOD CMP VALID");
break;
}
}
if (!found)
continue;
Log.d("XXX","METHOD FOUND: %s\n" + method.getName());
List<String> ptr = new ArrayList<String>();
Class[] paramTypes = method.getParameterTypes();
for (Class c : paramTypes) {
ptr.add(c.getName());
}
String[] pt = new String[ptr.size()];
ptr.toArray(pt);
GodotLib.method(p_name,method.getName(),method.getReturnType().getName(),pt);
}
Godot.singletons[Godot.singleton_count++]=this;
}
protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {
}
protected void onMainPause() {}
protected void onMainResume() {}
protected void onMainDestroy() {}
protected void onGLDrawFrame(GL10 gl) {}
protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
//protected void onGLSurfaceCreated(GL10 gl, EGLConfig config) {} // singletons won't be ready until first GodotLib.step()
public void registerMethods() {}
}
/*
protected List<SingletonBase> singletons = new ArrayList<SingletonBase>();
protected void instanceSingleton(SingletonBase s) {
s.registerMethods();
singletons.add(s);
}
*/
private String[] command_line;
public GodotView mView;
private boolean godot_initialized=false;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
public FrameLayout layout;
public RelativeLayout adLayout;
static public GodotIO io;
public static void setWindowTitle(String title) {
//setTitle(title);
}
static SingletonBase singletons[] = new SingletonBase[MAX_SINGLETONS];
static int singleton_count=0;
public interface ResultCallback {
public void callback(int requestCode, int resultCode, Intent data);
};
public ResultCallback result_callback;
private PaymentsManager mPaymentsManager = null;
@Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if(requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE){
mPaymentsManager.processPurchaseResponse(resultCode, data);
}else if (result_callback != null) {
result_callback.callback(requestCode, resultCode, data);
result_callback = null;
};
for(int i=0;i<singleton_count;i++) {
singletons[i].onMainActivityResult(requestCode,resultCode,data);
}
};
public void onVideoInit(boolean use_gl2) {
// mView = new GodotView(getApplication(),io,use_gl2);
// setContentView(mView);
layout = new FrameLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
setContentView(layout);
// GodotEditText layout
GodotEditText edittext = new GodotEditText(this);
edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
// ...add to FrameLayout
layout.addView(edittext);
mView = new GodotView(getApplication(),io,use_gl2,use_32_bits, this);
layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
mView.setKeepScreenOn(true);
edittext.setView(mView);
io.setEdit(edittext);
// Ad layout
adLayout = new RelativeLayout(this);
adLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
layout.addView(adLayout);
}
private static Godot _self;
public static Godot getInstance(){
return Godot._self;
}
private String[] getCommandLine() {
InputStream is;
try {
is = getAssets().open("_cl_");
byte[] len = new byte[4];
int r = is.read(len);
if (r<4) {
Log.d("XXX","**ERROR** Wrong cmdline length.\n");
Log.d("GODOT", "**ERROR** Wrong cmdline length.\n");
return new String[0];
}
int argc=((int)(len[3]&0xFF)<<24) | ((int)(len[2]&0xFF)<<16) | ((int)(len[1]&0xFF)<<8) | ((int)(len[0]&0xFF));
String[] cmdline = new String[argc];
for(int i=0;i<argc;i++) {
r = is.read(len);
if (r<4) {
Log.d("GODOT", "**ERROR** Wrong cmdline param lenght.\n");
return new String[0];
}
int strlen=((int)(len[3]&0xFF)<<24) | ((int)(len[2]&0xFF)<<16) | ((int)(len[1]&0xFF)<<8) | ((int)(len[0]&0xFF));
if (strlen>65535) {
Log.d("GODOT", "**ERROR** Wrong command len\n");
return new String[0];
}
byte[] arg = new byte[strlen];
r = is.read(arg);
if (r==strlen) {
cmdline[i]=new String(arg,"UTF-8");
}
}
return cmdline;
} catch (Exception e) {
e.printStackTrace();
Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage());
return new String[0];
}
}
String expansion_pack_path;
private void initializeGodot() {
if (expansion_pack_path!=null) {
String[] new_cmdline;
int cll=0;
if (command_line!=null) {
Log.d("GODOT", "initializeGodot: command_line: is not null" );
new_cmdline = new String[ command_line.length + 2 ];
cll=command_line.length;
for(int i=0;i<command_line.length;i++) {
new_cmdline[i]=command_line[i];
}
} else {
Log.d("GODOT", "initializeGodot: command_line: is null" );
new_cmdline = new String[ 2 ];
}
new_cmdline[cll]="-main_pack";
new_cmdline[cll+1]=expansion_pack_path;
command_line=new_cmdline;
}
io = new GodotIO(this);
io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
GodotLib.io=io;
Log.d("GODOT", "command_line is null? " + ((command_line == null)?"yes":"no"));
/*if(command_line != null){
Log.d("GODOT", "Command Line:");
for(int w=0;w <command_line.length;w++){
Log.d("GODOT"," " + command_line[w]);
}
}*/
GodotLib.initialize(this,io.needsReloadHooks(),command_line,getAssets());
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
result_callback = null;
mPaymentsManager = PaymentsManager.createManager(this).initService();
godot_initialized=true;
}
@Override
public void onServiceConnected(Messenger m) {
mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
@Override
protected void onCreate(Bundle icicle) {
Log.d("GODOT", "** GODOT ACTIVITY CREATED HERE ***\n");
super.onCreate(icicle);
_self = this;
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//check for apk expansion API
if (true) {
boolean md5mismatch = false;
command_line = getCommandLine();
boolean use_apk_expansion=false;
String main_pack_md5=null;
String main_pack_key=null;
List<String> new_args = new LinkedList<String>();
for(int i=0;i<command_line.length;i++) {
boolean has_extra = i< command_line.length -1;
if (command_line[i].equals("-use_depth_32")) {
use_32_bits=true;
} else if (command_line[i].equals("-use_immersive")) {
use_immersive=true;
if(Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
window.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
UiChangeListener();
}
} else if (command_line[i].equals("-use_apk_expansion")) {
use_apk_expansion=true;
} else if (has_extra && command_line[i].equals("-apk_expansion_md5")) {
main_pack_md5=command_line[i+1];
i++;
} else if (has_extra && command_line[i].equals("-apk_expansion_key")) {
main_pack_key=command_line[i+1];
SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putString("store_public_key", main_pack_key);
editor.commit();
i++;
} else if (command_line[i].trim().length()!=0){
new_args.add(command_line[i]);
}
}
if (new_args.isEmpty()){
command_line=null;
}else{
command_line = new_args.toArray(new String[new_args.size()]);
}
if (use_apk_expansion && main_pack_md5!=null && main_pack_key!=null) {
//check that environment is ok!
if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED )) {
Log.d("GODOT", "**ERROR! No media mounted!");
//show popup and die
}
// Build the full path to the app's expansion files
try {
expansion_pack_path = Environment.getExternalStorageDirectory().toString() + "/Android/obb/"+this.getPackageName();
expansion_pack_path+="/"+"main."+getPackageManager().getPackageInfo(getPackageName(), 0).versionCode+"."+this.getPackageName()+".obb";
} catch (Exception e) {
e.printStackTrace();
}
File f = new File(expansion_pack_path);
boolean pack_valid = true;
Log.d("GODOT","**PACK** - Path "+expansion_pack_path);
if (!f.exists()) {
pack_valid=false;
Log.d("GODOT","**PACK** - File does not exist");
} else if( obbIsCorrupted(expansion_pack_path, main_pack_md5)){
Log.d("GODOT", "**PACK** - Expansion pack (obb) is corrupted");
pack_valid = false;
try{
f.delete();
}catch(Exception e){
Log.d("GODOT", "**PACK** - Error deleting corrupted expansion pack (obb)");
}
}
if (!pack_valid) {
Log.d("GODOT", "Pack Invalid, try re-downloading.");
Intent notifierIntent = new Intent(this, this.getClass());
notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
int startResult;
try {
Log.d("GODOT", "INITIALIZING DOWNLOAD");
startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
getApplicationContext(),
pendingIntent,
GodotDownloaderService.class);
Log.d("GODOT", "DOWNLOAD SERVICE FINISHED:" + startResult);
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
Log.d("GODOT", "DOWNLOAD REQUIRED");
// This is where you do set up to display the download
// progress (next step)
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
GodotDownloaderService.class);
setContentView(com.godot.game.R.layout.downloading_expansion);
mPB = (ProgressBar) findViewById(com.godot.game.R.id.progressBar);
mStatusText = (TextView) findViewById(com.godot.game.R.id.statusText);
mProgressFraction = (TextView) findViewById(com.godot.game.R.id.progressAsFraction);
mProgressPercent = (TextView) findViewById(com.godot.game.R.id.progressAsPercentage);
mAverageSpeed = (TextView) findViewById(com.godot.game.R.id.progressAverageSpeed);
mTimeRemaining = (TextView) findViewById(com.godot.game.R.id.progressTimeRemaining);
mDashboard = findViewById(com.godot.game.R.id.downloaderDashboard);
mCellMessage = findViewById(com.godot.game.R.id.approveCellular);
mPauseButton = (Button) findViewById(com.godot.game.R.id.pauseButton);
mWiFiSettingsButton = (Button) findViewById(com.godot.game.R.id.wifiSettingsButton);
return;
} else{
Log.d("GODOT", "NO DOWNLOAD REQUIRED");
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
Log.d("GODOT", "Error downloading expansion package:" + e.getMessage());
}
}
}
}
initializeGodot();
// instanceSingleton( new GodotFacebook(this) );
}
@Override protected void onDestroy(){
if(mPaymentsManager != null ) mPaymentsManager.destroy();
for(int i=0;i<singleton_count;i++) {
singletons[i].onMainDestroy();
}
super.onDestroy();
}
@Override protected void onPause() {
super.onPause();
if (!godot_initialized){
if (null != mDownloaderClientStub) {
mDownloaderClientStub.disconnect(this);
}
return;
}
mView.onPause();
mSensorManager.unregisterListener(this);
GodotLib.focusout();
for(int i=0;i<singleton_count;i++) {
singletons[i].onMainPause();
}
}
@Override protected void onResume() {
super.onResume();
if (!godot_initialized){
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
return;
}
mView.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
GodotLib.focusin();
if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
Window window = getWindow();
window.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
for(int i=0;i<singleton_count;i++) {
singletons[i].onMainResume();
}
}
public void UiChangeListener() {
final View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
});
}
@Override public void onSensorChanged(SensorEvent event) {
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int displayRotation = display.getRotation();
float[] adjustedValues = new float[3];
final int axisSwap[][] = {
{ 1, -1, 0, 1 }, // ROTATION_0
{-1, -1, 1, 0 }, // ROTATION_90
{-1, 1, 0, 1 }, // ROTATION_180
{ 1, 1, 1, 0 } }; // ROTATION_270
final int[] as = axisSwap[displayRotation];
adjustedValues[0] = (float)as[0] * event.values[ as[2] ];
adjustedValues[1] = (float)as[1] * event.values[ as[3] ];
adjustedValues[2] = event.values[2];
float x = adjustedValues[0];
float y = adjustedValues[1];
float z = adjustedValues[2];
GodotLib.accelerometer(x,y,z);
}
@Override public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
/*
@Override public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
System.out.printf("** BACK REQUEST!\n");
GodotLib.quit();
return true;
}
System.out.printf("** OTHER KEY!\n");
return false;
}
*/
@Override public void onBackPressed() {
System.out.printf("** BACK REQUEST!\n");
GodotLib.quit();
}
public void forceQuit() {
System.exit(0);
}
private boolean obbIsCorrupted(String f, String main_pack_md5){
try {
InputStream fis = new FileInputStream(f);
// Create MD5 Hash
byte[] buffer = new byte[16384];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
byte[] messageDigest = complete.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i=0; i<messageDigest.length; i++) {
String s = Integer.toHexString(0xFF & messageDigest[i]);
if (s.length()==1) {
s="0"+s;
}
hexString.append(s);
}
String md5str = hexString.toString();
//Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5);
if (!md5str.equals(main_pack_md5)) {
Log.d("GODOT","**PACK MD5 MISMATCH???** - MD5 Found: "+md5str+" "+Integer.toString(md5str.length())+" - MD5 Expected: "+main_pack_md5+" "+Integer.toString(main_pack_md5.length()));
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
Log.d("GODOT","**PACK FAIL**");
return true;
}
}
//@Override public boolean dispatchTouchEvent (MotionEvent event) {
public boolean gotTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int evcount=event.getPointerCount();
if (evcount==0)
return true;
int[] arr = new int[event.getPointerCount()*3];
for(int i=0;i<event.getPointerCount();i++) {
arr[i*3+0]=(int)event.getPointerId(i);
arr[i*3+1]=(int)event.getX(i);
arr[i*3+2]=(int)event.getY(i);
}
//System.out.printf("gaction: %d\n",event.getAction());
switch(event.getAction()&MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
GodotLib.touch(0,0,evcount,arr);
//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
} break;
case MotionEvent.ACTION_MOVE: {
GodotLib.touch(1,0,evcount,arr);
//for(int i=0;i<event.getPointerCount();i++) {
// System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
//}
} break;
case MotionEvent.ACTION_POINTER_UP: {
final int indexPointUp = event.getActionIndex();
final int pointer_idx = event.getPointerId(indexPointUp);
GodotLib.touch(4,pointer_idx,evcount,arr);
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_POINTER_DOWN: {
int pointer_idx = event.getActionIndex();
GodotLib.touch(3,pointer_idx,evcount,arr);
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
GodotLib.touch(2,0,evcount,arr);
//for(int i=0;i<event.getPointerCount();i++) {
// System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
//}
} break;
}
return true;
}
@Override public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
String s = event.getCharacters();
if (s == null || s.length() == 0)
return super.onKeyMultiple(inKeyCode, repeatCount, event);
final char[] cc = s.toCharArray();
int cnt = 0;
for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0);
if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
final Activity me = this;
queueEvent(new Runnable() {
// This method will be called on the rendering thread:
public void run() {
for (int i = 0, n = cc.length; i < n; i++) {
int keyCode;
if ((keyCode = cc[i]) != 0) {
// Simulate key down and up...
GodotLib.key(0, keyCode, true);
GodotLib.key(0, keyCode, false);
}
}
}
});
return true;
}
private void queueEvent(Runnable runnable) {
// TODO Auto-generated method stub
}
public PaymentsManager getPaymentsManager() {
return mPaymentsManager;
}
// public void setPaymentsManager(PaymentsManager mPaymentsManager) {
// this.mPaymentsManager = mPaymentsManager;
// };
// Audio
/**
* The download state should trigger changes in the UI --- it may be useful
* to show the state as being indeterminate at times. This sample can be
* considered a guideline.
*/
@Override
public void onDownloadStateChanged(int newState) {
Log.d("GODOT", "onDownloadStateChanged:" + newState);
setState(newState);
boolean showDashboard = true;
boolean showCellMessage = false;
boolean paused;
boolean indeterminate;
switch (newState) {
case IDownloaderClient.STATE_IDLE:
Log.d("GODOT", "STATE IDLE");
// STATE_IDLE means the service is listening, so it's
// safe to start making calls via mRemoteService.
paused = false;
indeterminate = true;
break;
case IDownloaderClient.STATE_CONNECTING:
case IDownloaderClient.STATE_FETCHING_URL:
Log.d("GODOT", "STATE CONNECTION / FETCHING URL");
showDashboard = true;
paused = false;
indeterminate = true;
break;
case IDownloaderClient.STATE_DOWNLOADING:
Log.d("GODOT", "STATE DOWNLOADING");
paused = false;
showDashboard = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_FAILED_CANCELED:
case IDownloaderClient.STATE_FAILED:
case IDownloaderClient.STATE_FAILED_FETCHING_URL:
case IDownloaderClient.STATE_FAILED_UNLICENSED:
Log.d("GODOT", "MANY TYPES OF FAILING");
paused = true;
showDashboard = false;
indeterminate = false;
break;
case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
Log.d("GODOT", "PAUSED FOR SOME STUPID REASON");
showDashboard = false;
paused = true;
indeterminate = false;
showCellMessage = true;
break;
case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
Log.d("GODOT", "PAUSED BY STUPID USER");
paused = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_PAUSED_ROAMING:
case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
Log.d("GODOT", "PAUSED BY ROAMING WTF!?");
paused = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_COMPLETED:
Log.d("GODOT", "COMPLETED");
showDashboard = false;
paused = false;
indeterminate = false;
// validateXAPKZipFiles();
initializeGodot();
return;
default:
Log.d("GODOT", "DEFAULT ????");
paused = true;
indeterminate = true;
showDashboard = true;
}
int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;
if (mDashboard.getVisibility() != newDashboardVisibility) {
mDashboard.setVisibility(newDashboardVisibility);
}
int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;
if (mCellMessage.getVisibility() != cellMessageVisibility) {
mCellMessage.setVisibility(cellMessageVisibility);
}
mPB.setIndeterminate(indeterminate);
setButtonPausedState(paused);
}
@Override
public void onDownloadProgress(DownloadProgressInfo progress) {
mAverageSpeed.setText(getString(com.godot.game.R.string.kilobytes_per_second,
Helpers.getSpeedString(progress.mCurrentSpeed)));
mTimeRemaining.setText(getString(com.godot.game.R.string.time_remaining,
Helpers.getTimeRemaining(progress.mTimeRemaining)));
progress.mOverallTotal = progress.mOverallTotal;
mPB.setMax((int) (progress.mOverallTotal >> 8));
mPB.setProgress((int) (progress.mOverallProgress >> 8));
mProgressPercent.setText(Long.toString(progress.mOverallProgress
* 100 /
progress.mOverallTotal) + "%");
mProgressFraction.setText(Helpers.getDownloadProgressString
(progress.mOverallProgress,
progress.mOverallTotal));
}
}

View File

@@ -1,30 +0,0 @@
package com.android.godot;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
/**
* You should start your derived downloader class when this receiver gets the message
* from the alarm service using the provided service helper function within the
* DownloaderClientMarshaller. This class must be then registered in your AndroidManifest.xml
* file with a section like this:
* <receiver android:name=".GodotDownloaderAlarmReceiver"/>
*/
public class GodotDownloaderAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("GODOT", "Alarma recivida");
try {
DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, GodotDownloaderService.class);
} catch (NameNotFoundException e) {
e.printStackTrace();
Log.d("GODOT", "Exception: " + e.getClass().getName() + ":" + e.getMessage());
}
}
}

View File

@@ -1,56 +0,0 @@
package com.android.godot;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.google.android.vending.expansion.downloader.impl.DownloaderService;
/**
* This class demonstrates the minimal client implementation of the
* DownloaderService from the Downloader library.
*/
public class GodotDownloaderService extends DownloaderService {
// stuff for LVL -- MODIFY FOR YOUR APPLICATION!
private static final String BASE64_PUBLIC_KEY = "REPLACE THIS WITH YOUR PUBLIC KEY";
// used by the preference obfuscater
private static final byte[] SALT = new byte[] {
1, 43, -12, -1, 54, 98,
-100, -12, 43, 2, -8, -4, 9, 5, -106, -108, -33, 45, -1, 84
};
/**
* This public key comes from your Android Market publisher account, and it
* used by the LVL to validate responses from Market on your behalf.
*/
@Override
public String getPublicKey() {
SharedPreferences prefs = getApplicationContext().getSharedPreferences("app_data_keys", Context.MODE_PRIVATE);
Log.d("GODOT", "getting public key:" + prefs.getString("store_public_key", null));
return prefs.getString("store_public_key", null);
// return BASE64_PUBLIC_KEY;
}
/**
* This is used by the preference obfuscater to make sure that your
* obfuscated preferences are different than the ones used by other
* applications.
*/
@Override
public byte[] getSALT() {
return SALT;
}
/**
* Fill this in with the class name for your alarm receiver. We do this
* because receivers must be unique across all of Android (it's a good idea
* to make sure that your receiver is in your unique package)
*/
@Override
public String getAlarmReceiverClassName() {
Log.d("GODOT", "getAlarmReceiverClassName()");
return GodotDownloaderAlarmReceiver.class.getName();
}
}

View File

@@ -1,673 +0,0 @@
/*************************************************************************/
/* GodotIO.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import java.util.HashMap;
import java.util.Locale;
import android.net.Uri;
import android.content.Intent;
import android.content.res.AssetManager;
import java.io.InputStream;
import java.io.IOException;
import android.app.*;
import android.content.*;
import android.view.*;
import android.view.inputmethod.InputMethodManager;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import android.content.pm.ActivityInfo;
import com.android.godot.input.*;
//android.os.Build
// Wrapper for native library
public class GodotIO {
AssetManager am;
Godot activity;
GodotEditText edit;
Context applicationContext;
MediaPlayer mediaPlayer;
final int SCREEN_LANDSCAPE=0;
final int SCREEN_PORTRAIT=1;
final int SCREEN_REVERSE_LANDSCAPE=2;
final int SCREEN_REVERSE_PORTRAIT=3;
final int SCREEN_SENSOR_LANDSCAPE=4;
final int SCREEN_SENSOR_PORTRAIT=5;
final int SCREEN_SENSOR=6;
/////////////////////////
/// FILES
/////////////////////////
public int last_file_id=1;
class AssetData {
public boolean eof=false;
public String path;
public InputStream is;
public int len;
public int pos;
}
HashMap<Integer,AssetData> streams;
public int file_open(String path,boolean write) {
//System.out.printf("file_open: Attempt to Open %s\n",path);
//Log.v("MyApp", "TRYING TO OPEN FILE: " + path);
if (write)
return -1;
AssetData ad = new AssetData();
try {
ad.is = am.open(path);
} catch (Exception e) {
//System.out.printf("Exception on file_open: %s\n",path);
return -1;
}
try {
ad.len=ad.is.available();
} catch (Exception e) {
System.out.printf("Exception availabling on file_open: %s\n",path);
return -1;
}
ad.path=path;
ad.pos=0;
++last_file_id;
streams.put(last_file_id,ad);
return last_file_id;
}
public int file_get_size(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_get_size: Invalid file id: %d\n",id);
return -1;
}
return streams.get(id).len;
}
public void file_seek(int id,int bytes) {
if (!streams.containsKey(id)) {
System.out.printf("file_get_size: Invalid file id: %d\n",id);
return;
}
//seek sucks
AssetData ad = streams.get(id);
if (bytes>ad.len)
bytes=ad.len;
if (bytes<0)
bytes=0;
try {
if (bytes > (int)ad.pos) {
int todo=bytes-(int)ad.pos;
while(todo>0) {
todo-=ad.is.skip(todo);
}
ad.pos=bytes;
} else if (bytes<(int)ad.pos) {
ad.is=am.open(ad.path);
ad.pos=bytes;
int todo=bytes;
while(todo>0) {
todo-=ad.is.skip(todo);
}
}
ad.eof=false;
} catch (IOException e) {
System.out.printf("Exception on file_seek: %s\n",e);
return;
}
}
public int file_tell(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_read: Can't tell eof for invalid file id: %d\n",id);
return 0;
}
AssetData ad = streams.get(id);
return ad.pos;
}
public boolean file_eof(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_read: Can't check eof for invalid file id: %d\n",id);
return false;
}
AssetData ad = streams.get(id);
return ad.eof;
}
public byte[] file_read(int id, int bytes) {
if (!streams.containsKey(id)) {
System.out.printf("file_read: Can't read invalid file id: %d\n",id);
return new byte[0];
}
AssetData ad = streams.get(id);
if (ad.pos + bytes > ad.len) {
bytes=ad.len-ad.pos;
ad.eof=true;
}
if (bytes==0) {
return new byte[0];
}
byte[] buf1=new byte[bytes];
int r=0;
try {
r = ad.is.read(buf1);
} catch (IOException e) {
System.out.printf("Exception on file_read: %s\n",e);
return new byte[bytes];
}
if (r==0) {
return new byte[0];
}
ad.pos+=r;
if (r<bytes) {
byte[] buf2=new byte[r];
for(int i=0;i<r;i++)
buf2[i]=buf1[i];
return buf2;
} else {
return buf1;
}
}
public void file_close(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_close: Can't close invalid file id: %d\n",id);
return;
}
streams.remove(id);
}
/////////////////////////
/// DIRECTORIES
/////////////////////////
class AssetDir {
public String[] files;
public int current;
public String path;
}
public int last_dir_id=1;
HashMap<Integer,AssetDir> dirs;
public int dir_open(String path) {
AssetDir ad = new AssetDir();
ad.current=0;
ad.path=path;
try {
ad.files = am.list(path);
} catch (IOException e) {
System.out.printf("Exception on dir_open: %s\n",e);
return -1;
}
//System.out.printf("Opened dir: %s\n",path);
++last_dir_id;
dirs.put(last_dir_id,ad);
return last_dir_id;
}
public boolean dir_is_dir(int id) {
if (!dirs.containsKey(id)) {
System.out.printf("dir_next: invalid dir id: %d\n",id);
return false;
}
AssetDir ad = dirs.get(id);
//System.out.printf("go next: %d,%d\n",ad.current,ad.files.length);
int idx = ad.current;
if (idx>0)
idx--;
if (idx>=ad.files.length)
return false;
String fname = ad.files[idx];
try {
if (ad.path.equals(""))
am.open(fname);
else
am.open(ad.path+"/"+fname);
return false;
} catch (Exception e) {
return true;
}
}
public String dir_next(int id) {
if (!dirs.containsKey(id)) {
System.out.printf("dir_next: invalid dir id: %d\n",id);
return "";
}
AssetDir ad = dirs.get(id);
//System.out.printf("go next: %d,%d\n",ad.current,ad.files.length);
if (ad.current>=ad.files.length) {
ad.current++;
return "";
}
String r = ad.files[ad.current];
ad.current++;
return r;
}
public void dir_close(int id) {
if (!dirs.containsKey(id)) {
System.out.printf("dir_close: invalid dir id: %d\n",id);
return;
}
dirs.remove(id);
}
GodotIO(Godot p_activity) {
am=p_activity.getAssets();
activity=p_activity;
streams=new HashMap<Integer,AssetData>();
dirs=new HashMap<Integer,AssetDir>();
applicationContext = activity.getApplicationContext();
}
/////////////////////////
// AUDIO
/////////////////////////
private Object buf;
private Thread mAudioThread;
private AudioTrack mAudioTrack;
public Object audioInit(int sampleRate, int desiredFrames) {
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int frameSize = 4;
System.out.printf("audioInit: initializing audio:\n");
//Log.v("Godot", "Godot audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
// Let the user pick a larger buffer if they really want -- but ye
// gods they probably shouldn't, the minimums are horrifyingly high
// latency already
desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
audioStartThread();
//Log.v("Godot", "Godot audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
buf = new short[desiredFrames * 2];
return buf;
}
public void audioStartThread() {
mAudioThread = new Thread(new Runnable() {
public void run() {
mAudioTrack.play();
GodotLib.audio();
}
});
// I'd take REALTIME if I could get it!
mAudioThread.setPriority(Thread.MAX_PRIORITY);
mAudioThread.start();
}
public void audioWriteShortBuffer(short[] buffer) {
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(1);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w("Godot", "Godot audio: error return from write(short)");
return;
}
}
}
public void audioQuit() {
if (mAudioThread != null) {
try {
mAudioThread.join();
} catch(Exception e) {
Log.v("Godot", "Problem stopping audio thread: " + e);
}
mAudioThread = null;
//Log.v("Godot", "Finished waiting for audio thread");
}
if (mAudioTrack != null) {
mAudioTrack.stop();
mAudioTrack = null;
}
}
public void audioPause(boolean p_pause) {
if (p_pause)
mAudioTrack.pause();
else
mAudioTrack.play();
}
/////////////////////////
// MISCELANEOUS OS IO
/////////////////////////
public int openURI(String p_uri) {
try {
Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri);
String path = p_uri;
String type="";
if (path.startsWith("/")) {
//absolute path to filesystem, prepend file://
path="file://"+path;
if (p_uri.endsWith(".png") || p_uri.endsWith(".jpg") || p_uri.endsWith(".gif") || p_uri.endsWith(".webp")) {
type="image/*";
}
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
if (!type.equals("")) {
intent.setDataAndType(Uri.parse(path), type);
} else {
intent.setData(Uri.parse(path));
}
activity.startActivity(intent);
return 0;
} catch (ActivityNotFoundException e) {
return 1;
}
}
public String getDataDir() {
return activity.getFilesDir().getAbsolutePath();
}
public String getLocale() {
return Locale.getDefault().toString();
}
public String getModel() {
return Build.MODEL;
}
public boolean needsReloadHooks() {
return android.os.Build.VERSION.SDK_INT < 11;
}
public void showKeyboard(String p_existing_text) {
if(edit != null)
edit.showKeyboard(p_existing_text);
//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
};
public void hideKeyboard() {
if(edit != null)
edit.hideKeyboard();
InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
View v = activity.getCurrentFocus();
if (v != null) {
inputMgr.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
} else {
inputMgr.hideSoftInputFromWindow(new View(activity).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
};
public void setScreenOrientation(int p_orientation) {
switch(p_orientation) {
case SCREEN_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} break;
case SCREEN_PORTRAIT: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} break;
case SCREEN_REVERSE_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
} break;
case SCREEN_REVERSE_PORTRAIT: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} break;
case SCREEN_SENSOR_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} break;
case SCREEN_SENSOR_PORTRAIT: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
} break;
case SCREEN_SENSOR: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
} break;
}
};
public void setEdit(GodotEditText _edit) {
edit = _edit;
}
public void playVideo(String p_path)
{
Uri filePath = Uri.parse(p_path);
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(applicationContext, filePath);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch(IOException e)
{
System.out.println("IOError while playing video");
}
}
public boolean isVideoPlaying() {
if (mediaPlayer != null) {
return mediaPlayer.isPlaying();
}
return false;
}
public void pauseVideo() {
if (mediaPlayer != null) {
mediaPlayer.pause();
}
}
public void stopVideo() {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
}
public static final int SYSTEM_DIR_DESKTOP=0;
public static final int SYSTEM_DIR_DCIM=1;
public static final int SYSTEM_DIR_DOCUMENTS=2;
public static final int SYSTEM_DIR_DOWNLOADS=3;
public static final int SYSTEM_DIR_MOVIES=4;
public static final int SYSTEM_DIR_MUSIC=5;
public static final int SYSTEM_DIR_PICTURES=6;
public static final int SYSTEM_DIR_RINGTONES=7;
public String getSystemDir(int idx) {
String what="";
switch(idx) {
case SYSTEM_DIR_DESKTOP: {
//what=Environment.DIRECTORY_DOCUMENTS;
what=Environment.DIRECTORY_DOWNLOADS;
} break;
case SYSTEM_DIR_DCIM: {
what=Environment.DIRECTORY_DCIM;
} break;
case SYSTEM_DIR_DOCUMENTS: {
what=Environment.DIRECTORY_DOWNLOADS;
//what=Environment.DIRECTORY_DOCUMENTS;
} break;
case SYSTEM_DIR_DOWNLOADS: {
what=Environment.DIRECTORY_DOWNLOADS;
} break;
case SYSTEM_DIR_MOVIES: {
what=Environment.DIRECTORY_MOVIES;
} break;
case SYSTEM_DIR_MUSIC: {
what=Environment.DIRECTORY_MUSIC;
} break;
case SYSTEM_DIR_PICTURES: {
what=Environment.DIRECTORY_PICTURES;
} break;
case SYSTEM_DIR_RINGTONES: {
what=Environment.DIRECTORY_RINGTONES;
} break;
}
if (what.equals(""))
return "";
return Environment.getExternalStoragePublicDirectory(what).getAbsolutePath();
}
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
public static String unique_id="";
public String getUniqueID() {
return unique_id;
}
}

View File

@@ -1,66 +0,0 @@
/*************************************************************************/
/* GodotLib.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
// Wrapper for native library
public class GodotLib {
public static GodotIO io;
static {
System.loadLibrary("godot_android");
}
/**
* @param width the current view width
* @param height the current view height
*/
public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline,Object p_asset_manager);
public static native void resize(int width, int height,boolean reload);
public static native void newcontext(boolean p_32_bits);
public static native void quit();
public static native void step();
public static native void touch(int what,int pointer,int howmany, int[] arr);
public static native void accelerometer(float x, float y, float z);
public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
public static native void joybutton(int p_device, int p_but, boolean p_pressed);
public static native void joyaxis(int p_device, int p_axis, float p_value);
public static native void focusin();
public static native void focusout();
public static native void audio();
public static native void singleton(String p_name,Object p_object);
public static native void method(String p_sname,String p_name,String p_ret,String[] p_params);
public static native String getGlobal(String p_key);
public static native void callobject(int p_ID, String p_method, Object[] p_params);
public static native void calldeferred(int p_ID, String p_method, Object[] p_params);
}

View File

@@ -1,154 +0,0 @@
package com.android.godot;
import com.android.godot.Dictionary;
import android.app.Activity;
import android.util.Log;
public class GodotPaymentV3 extends Godot.SingletonBase {
private Godot activity;
private Integer purchaseCallbackId = 0;
private String accessToken;
private String purchaseValidationUrlPrefix;
private String transactionId;
public void purchase( String _sku, String _transactionId) {
final String sku = _sku;
final String transactionId = _transactionId;
activity.getPaymentsManager().setBaseSingleton(this);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.getPaymentsManager().requestPurchase(sku, transactionId);
}
});
}
/* public string requestPurchasedTicket(){
activity.getPaymentsManager()
}
*/
static public Godot.SingletonBase initialize(Activity p_activity) {
return new GodotPaymentV3(p_activity);
}
public GodotPaymentV3(Activity p_activity) {
registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume"});
activity=(Godot) p_activity;
}
public void consumeUnconsumedPurchases(){
activity.getPaymentsManager().setBaseSingleton(this);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.getPaymentsManager().consumeUnconsumedPurchases();
}
});
}
private String signature;
public String getSignature(){
return this.signature;
}
public void callbackSuccess(String ticket, String signature, String sku){
// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
}
public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > "+ticket+","+signature+","+sku);
GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
}
public void callbackSuccessNoUnconsumedPurchases(){
GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
}
public void callbackFail(){
GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
}
public void callbackCancel(){
GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[]{});
// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
}
public void callbackAlreadyOwned(String sku){
GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku});
}
public int getPurchaseCallbackId() {
return purchaseCallbackId;
}
public void setPurchaseCallbackId(int purchaseCallbackId) {
this.purchaseCallbackId = purchaseCallbackId;
}
public String getPurchaseValidationUrlPrefix(){
return this.purchaseValidationUrlPrefix ;
}
public void setPurchaseValidationUrlPrefix(String url){
this.purchaseValidationUrlPrefix = url;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public void setTransactionId(String transactionId){
this.transactionId = transactionId;
}
public String getTransactionId(){
return this.transactionId;
}
// request purchased items are not consumed
public void requestPurchased(){
activity.getPaymentsManager().setBaseSingleton(this);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.getPaymentsManager().requestPurchased();
}
});
}
// callback for requestPurchased()
public void callbackPurchased(String receipt, String signature, String sku){
GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[]{receipt, signature, sku});
}
// consume item automatically after purchase. default is true.
public void setAutoConsume(boolean autoConsume){
activity.getPaymentsManager().setAutoConsume(autoConsume);
}
// consume a specific item
public void consume(String sku){
activity.getPaymentsManager().consume(sku);
}
}

View File

@@ -1,661 +0,0 @@
/*************************************************************************/
/* GodotView.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.content.ContextWrapper;
import android.view.InputDevice;
import java.io.File;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
/**
* A simple GLSurfaceView sub-class that demonstrate how to perform
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
* details:
*
* - The class must use a custom context factory to enable 2.0 rendering.
* See ContextFactory class definition below.
*
* - The class must use a custom EGLConfigChooser to be able to select
* an EGLConfig that supports 2.0. This is done by providing a config
* specification to eglChooseConfig() that has the attribute
* EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
* set. See ConfigChooser class definition below.
*
* - The class must select the surface's format, then choose an EGLConfig
* that matches it exactly (with regards to red/green/blue/alpha channels
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
public class GodotView extends GLSurfaceView {
private static String TAG = "GodotView";
private static final boolean DEBUG = false;
private static Context ctx;
private static GodotIO io;
private static boolean firsttime=true;
private static boolean use_gl2=false;
private static boolean use_32=false;
private Godot activity;
public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, boolean p_use_32_bits, Godot p_activity) {
super(context);
ctx=context;
io=p_io;
use_gl2=p_use_gl2;
use_32=p_use_32_bits;
activity = p_activity;
if (!p_io.needsReloadHooks()) {
//will only work on SDK 11+!!
setPreserveEGLContextOnPause(true);
}
init(false, 16, 0);
}
public GodotView(Context context, boolean translucent, int depth, int stencil) {
super(context);
init(translucent, depth, stencil);
}
@Override public boolean onTouchEvent (MotionEvent event) {
return activity.gotTouchEvent(event);
};
public int get_godot_button(int keyCode) {
int button = 0;
switch (keyCode) {
case KeyEvent.KEYCODE_BUTTON_A: // Android A is SNES B
button = 0;
break;
case KeyEvent.KEYCODE_BUTTON_B:
button = 1;
break;
case KeyEvent.KEYCODE_BUTTON_X: // Android X is SNES Y
button = 2;
break;
case KeyEvent.KEYCODE_BUTTON_Y:
button = 3;
break;
case KeyEvent.KEYCODE_BUTTON_L1:
button = 4;
break;
case KeyEvent.KEYCODE_BUTTON_L2:
button = 6;
break;
case KeyEvent.KEYCODE_BUTTON_R1:
button = 5;
break;
case KeyEvent.KEYCODE_BUTTON_R2:
button = 7;
break;
case KeyEvent.KEYCODE_BUTTON_SELECT:
button = 10;
break;
case KeyEvent.KEYCODE_BUTTON_START:
button = 11;
break;
case KeyEvent.KEYCODE_BUTTON_THUMBL:
button = 8;
break;
case KeyEvent.KEYCODE_BUTTON_THUMBR:
button = 9;
break;
case KeyEvent.KEYCODE_DPAD_UP:
button = 12;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
button = 13;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
button = 14;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
button = 15;
break;
default:
button = keyCode - KeyEvent.KEYCODE_BUTTON_1;
break;
};
return button;
};
@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
return super.onKeyUp(keyCode, event);
};
int source = event.getSource();
if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) {
int button = get_godot_button(keyCode);
int device = event.getDeviceId();
GodotLib.joybutton(device, button, false);
return true;
} else {
GodotLib.key(keyCode, event.getUnicodeChar(0), false);
};
return super.onKeyUp(keyCode, event);
};
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
GodotLib.quit();
// press 'back' button should not terminate program
// normal handle 'back' event in game logic
return true;
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
return super.onKeyDown(keyCode, event);
};
int source = event.getSource();
//Log.e(TAG, String.format("Key down! source %d, device %d, joystick %d, %d, %d", event.getDeviceId(), source, (source & InputDevice.SOURCE_JOYSTICK), (source & InputDevice.SOURCE_DPAD), (source & InputDevice.SOURCE_GAMEPAD)));
if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) {
if (event.getRepeatCount() > 0) // ignore key echo
return true;
int button = get_godot_button(keyCode);
int device = event.getDeviceId();
//Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device));
GodotLib.joybutton(device, button, true);
return true;
} else {
GodotLib.key(keyCode, event.getUnicodeChar(0), true);
};
return super.onKeyDown(keyCode, event);
}
public float axis_value(MotionEvent p_event, InputDevice p_device, int p_axis, int p_pos) {
final InputDevice.MotionRange range = p_device.getMotionRange(p_axis, p_event.getSource());
if (range == null)
return 0;
//Log.e(TAG, String.format("axis ranges %f, %f, %f", range.getRange(), range.getMin(), range.getMax()));
final float flat = range.getFlat();
final float value =
p_pos < 0 ? p_event.getAxisValue(p_axis):
p_event.getHistoricalAxisValue(p_axis, p_pos);
final float absval = Math.abs(value);
if (absval <= flat) {
return 0;
};
final float ret = (value - range.getMin()) / range.getRange() * 2 - 1.0f;
return ret;
};
float[] last_axis_values = { 0, 0, 0, 0, -1, -1 };
boolean[] last_axis_buttons = { false, false, false, false, false, false }; // dpad up down left right, ltrigger, rtrigger
public void process_axis_state(MotionEvent p_event, int p_pos) {
int device_id = p_event.getDeviceId();
InputDevice device = p_event.getDevice();
float val;
val = axis_value(p_event, device, MotionEvent.AXIS_X, p_pos);
if (val != last_axis_values[0]) {
last_axis_values[0] = val;
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 0, val));
GodotLib.joyaxis(device_id, 0, val);
};
val = axis_value(p_event, device, MotionEvent.AXIS_Y, p_pos);
if (val != last_axis_values[1]) {
last_axis_values[1] = val;
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 1, val));
GodotLib.joyaxis(device_id, 1, val);
};
val = axis_value(p_event, device, MotionEvent.AXIS_Z, p_pos);
if (val != last_axis_values[2]) {
last_axis_values[2] = val;
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 2, val));
GodotLib.joyaxis(device_id, 2, val);
};
val = axis_value(p_event, device, MotionEvent.AXIS_RZ, p_pos);
if (val != last_axis_values[3]) {
last_axis_values[3] = val;
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 3, val));
GodotLib.joyaxis(device_id, 3, val);
};
val = axis_value(p_event, device, MotionEvent.AXIS_LTRIGGER, p_pos);
if (val != last_axis_values[4]) {
last_axis_values[4] = val;
if ((val != 0) != (last_axis_buttons[4])) {
last_axis_buttons[4] = (val != 0);
GodotLib.joybutton(device_id, 6, (val != 0));
};
};
val = axis_value(p_event, device, MotionEvent.AXIS_RTRIGGER, p_pos);
if (val != last_axis_values[5]) {
last_axis_values[5] = val;
if ((val != 0) != (last_axis_buttons[5])) {
last_axis_buttons[5] = (val != 0);
GodotLib.joybutton(device_id, 7, (val != 0));
};
};
val = axis_value(p_event, device, MotionEvent.AXIS_HAT_Y, p_pos);
if (last_axis_buttons[0] != (val > 0)) {
last_axis_buttons[0] = val > 0;
GodotLib.joybutton(device_id, 12, val > 0);
};
if (last_axis_buttons[1] != (val < 0)) {
last_axis_buttons[1] = val < 0;
GodotLib.joybutton(device_id, 13, val > 0);
};
val = axis_value(p_event, device, MotionEvent.AXIS_HAT_X, p_pos);
if (last_axis_buttons[2] != (val < 0)) {
last_axis_buttons[2] = val < 0;
GodotLib.joybutton(device_id, 14, val < 0);
};
if (last_axis_buttons[3] != (val > 0)) {
last_axis_buttons[3] = val > 0;
GodotLib.joybutton(device_id, 15, val > 0);
};
};
@Override public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
// Process all historical movement samples in the batch
final int historySize = event.getHistorySize();
// Process the movements starting from the
// earliest historical position in the batch
for (int i = 0; i < historySize; i++) {
// Process the event at historical position i
process_axis_state(event, i);
}
// Process the current movement sample in the batch (position -1)
process_axis_state(event, -1);
return true;
};
return super.onGenericMotionEvent(event);
};
private void init(boolean translucent, int depth, int stencil) {
this.setFocusableInTouchMode(true);
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
* If we want a translucent one, we should change the surface's
* format here, using PixelFormat.TRANSLUCENT for GL Surfaces
* is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
*/
if (translucent) {
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
/* Setup the context factory for 2.0 rendering.
* See ContextFactory class definition below
*/
setEGLContextFactory(new ContextFactory());
/* We need to choose an EGLConfig that matches the format of
* our surface exactly. This is going to be done in our
* custom config chooser. See ConfigChooser class definition
* below.
*/
if (use_32) {
setEGLConfigChooser( translucent ?
new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(8, 8, 8, 8, 16, stencil)) :
new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(5, 6, 5, 0, 16, stencil)) );
} else {
setEGLConfigChooser( translucent ?
new ConfigChooser(8, 8, 8, 8, 16, stencil) :
new ConfigChooser(5, 6, 5, 0, 16, stencil) );
}
/* Set the renderer responsible for frame rendering */
setRenderer(new Renderer());
}
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
if (use_gl2)
Log.w(TAG, "creating OpenGL ES 2.0 context :");
else
Log.w(TAG, "creating OpenGL ES 1.1 context :");
checkEglError("Before eglCreateContext", egl);
int[] attrib_list2 = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl2?attrib_list2:null);
checkEglError("After eglCreateContext", egl);
return context;
}
public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
egl.eglDestroyContext(display, context);
}
}
private static void checkEglError(String prompt, EGL10 egl) {
int error;
while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
}
}
/* Fallback if 32bit View is not supported*/
private static class FallbackConfigChooser extends ConfigChooser {
private ConfigChooser fallback;
public FallbackConfigChooser(int r, int g, int b, int a, int depth, int stencil, ConfigChooser fallback) {
super(r, g, b, a, depth, stencil);
this.fallback = fallback;
}
@Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
EGLConfig ec = super.chooseConfig(egl, display, configs);
if (ec == null) {
Log.w(TAG, "Trying ConfigChooser fallback");
ec = fallback.chooseConfig(egl, display, configs);
use_32=false;
}
return ec;
}
}
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
mRedSize = r;
mGreenSize = g;
mBlueSize = b;
mAlphaSize = a;
mDepthSize = depth;
mStencilSize = stencil;
}
/* This EGL config specification is used to specify 2.0 rendering.
* We use a minimum size of 4 bits for red/green/blue, but will
* perform actual matching in chooseConfig() below.
*/
private static int EGL_OPENGL_ES2_BIT = 4;
private static int[] s_configAttribs2 =
{
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
// EGL10.EGL_DEPTH_SIZE, 16,
// EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL10.EGL_NONE
};
private static int[] s_configAttribs =
{
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
// EGL10.EGL_DEPTH_SIZE, 16,
// EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
EGL10.EGL_NONE
};
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
/* Get the number of minimally matching EGL configurations
*/
int[] num_config = new int[1];
egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, null, 0, num_config);
int numConfigs = num_config[0];
if (numConfigs <= 0) {
throw new IllegalArgumentException("No configs match configSpec");
}
/* Allocate then read the array of minimally matching EGL configs
*/
EGLConfig[] configs = new EGLConfig[numConfigs];
egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, configs, numConfigs, num_config);
if (DEBUG) {
printConfigs(egl, display, configs);
}
/* Now return the "best" one
*/
return chooseConfig(egl, display, configs);
}
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
EGLConfig[] configs) {
for(EGLConfig config : configs) {
int d = findConfigAttrib(egl, display, config,
EGL10.EGL_DEPTH_SIZE, 0);
int s = findConfigAttrib(egl, display, config,
EGL10.EGL_STENCIL_SIZE, 0);
// We need at least mDepthSize and mStencilSize bits
if (d < mDepthSize || s < mStencilSize)
continue;
// We want an *exact* match for red/green/blue/alpha
int r = findConfigAttrib(egl, display, config,
EGL10.EGL_RED_SIZE, 0);
int g = findConfigAttrib(egl, display, config,
EGL10.EGL_GREEN_SIZE, 0);
int b = findConfigAttrib(egl, display, config,
EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config,
EGL10.EGL_ALPHA_SIZE, 0);
if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
return config;
}
return null;
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
EGLConfig config, int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
private void printConfigs(EGL10 egl, EGLDisplay display,
EGLConfig[] configs) {
int numConfigs = configs.length;
Log.w(TAG, String.format("%d configurations", numConfigs));
for (int i = 0; i < numConfigs; i++) {
Log.w(TAG, String.format("Configuration %d:\n", i));
printConfig(egl, display, configs[i]);
}
}
private void printConfig(EGL10 egl, EGLDisplay display,
EGLConfig config) {
int[] attributes = {
EGL10.EGL_BUFFER_SIZE,
EGL10.EGL_ALPHA_SIZE,
EGL10.EGL_BLUE_SIZE,
EGL10.EGL_GREEN_SIZE,
EGL10.EGL_RED_SIZE,
EGL10.EGL_DEPTH_SIZE,
EGL10.EGL_STENCIL_SIZE,
EGL10.EGL_CONFIG_CAVEAT,
EGL10.EGL_CONFIG_ID,
EGL10.EGL_LEVEL,
EGL10.EGL_MAX_PBUFFER_HEIGHT,
EGL10.EGL_MAX_PBUFFER_PIXELS,
EGL10.EGL_MAX_PBUFFER_WIDTH,
EGL10.EGL_NATIVE_RENDERABLE,
EGL10.EGL_NATIVE_VISUAL_ID,
EGL10.EGL_NATIVE_VISUAL_TYPE,
0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
EGL10.EGL_SAMPLES,
EGL10.EGL_SAMPLE_BUFFERS,
EGL10.EGL_SURFACE_TYPE,
EGL10.EGL_TRANSPARENT_TYPE,
EGL10.EGL_TRANSPARENT_RED_VALUE,
EGL10.EGL_TRANSPARENT_GREEN_VALUE,
EGL10.EGL_TRANSPARENT_BLUE_VALUE,
0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
EGL10.EGL_LUMINANCE_SIZE,
EGL10.EGL_ALPHA_MASK_SIZE,
EGL10.EGL_COLOR_BUFFER_TYPE,
EGL10.EGL_RENDERABLE_TYPE,
0x3042 // EGL10.EGL_CONFORMANT
};
String[] names = {
"EGL_BUFFER_SIZE",
"EGL_ALPHA_SIZE",
"EGL_BLUE_SIZE",
"EGL_GREEN_SIZE",
"EGL_RED_SIZE",
"EGL_DEPTH_SIZE",
"EGL_STENCIL_SIZE",
"EGL_CONFIG_CAVEAT",
"EGL_CONFIG_ID",
"EGL_LEVEL",
"EGL_MAX_PBUFFER_HEIGHT",
"EGL_MAX_PBUFFER_PIXELS",
"EGL_MAX_PBUFFER_WIDTH",
"EGL_NATIVE_RENDERABLE",
"EGL_NATIVE_VISUAL_ID",
"EGL_NATIVE_VISUAL_TYPE",
"EGL_PRESERVED_RESOURCES",
"EGL_SAMPLES",
"EGL_SAMPLE_BUFFERS",
"EGL_SURFACE_TYPE",
"EGL_TRANSPARENT_TYPE",
"EGL_TRANSPARENT_RED_VALUE",
"EGL_TRANSPARENT_GREEN_VALUE",
"EGL_TRANSPARENT_BLUE_VALUE",
"EGL_BIND_TO_TEXTURE_RGB",
"EGL_BIND_TO_TEXTURE_RGBA",
"EGL_MIN_SWAP_INTERVAL",
"EGL_MAX_SWAP_INTERVAL",
"EGL_LUMINANCE_SIZE",
"EGL_ALPHA_MASK_SIZE",
"EGL_COLOR_BUFFER_TYPE",
"EGL_RENDERABLE_TYPE",
"EGL_CONFORMANT"
};
int[] value = new int[1];
for (int i = 0; i < attributes.length; i++) {
int attribute = attributes[i];
String name = names[i];
if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
} else {
// Log.w(TAG, String.format(" %s: failed\n", name));
while (egl.eglGetError() != EGL10.EGL_SUCCESS);
}
}
}
// Subclasses can adjust these values:
protected int mRedSize;
protected int mGreenSize;
protected int mBlueSize;
protected int mAlphaSize;
protected int mDepthSize;
protected int mStencilSize;
private int[] mValue = new int[1];
}
private static class Renderer implements GLSurfaceView.Renderer {
public void onDrawFrame(GL10 gl) {
GodotLib.step();
for(int i=0;i<Godot.singleton_count;i++) {
Godot.singletons[i].onGLDrawFrame(gl);
}
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GodotLib.resize(width, height,!firsttime);
firsttime=false;
for(int i=0;i<Godot.singleton_count;i++) {
Godot.singletons[i].onGLSurfaceChanged(gl, width, height);
}
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GodotLib.newcontext(use_32);
}
}
}

View File

@@ -1,133 +0,0 @@
package com.android.godot.input;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
import com.android.godot.*;
import android.os.Handler;
import android.os.Message;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.EditorInfo;
public class GodotEditText extends EditText {
// ===========================================================
// Constants
// ===========================================================
private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
// ===========================================================
// Fields
// ===========================================================
private GodotView mView;
private GodotTextInputWrapper mInputWrapper;
private static Handler sHandler;
private String mOriginText;
// ===========================================================
// Constructors
// ===========================================================
public GodotEditText(final Context context) {
super(context);
this.initView();
}
public GodotEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
this.initView();
}
public GodotEditText(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
this.initView();
}
protected void initView() {
this.setPadding(0, 0, 0, 0);
this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
sHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case HANDLER_OPEN_IME_KEYBOARD:
{
GodotEditText edit = (GodotEditText) msg.obj;
String text = edit.mOriginText;
if (edit.requestFocus())
{
edit.removeTextChangedListener(edit.mInputWrapper);
edit.setText("");
edit.append(text);
edit.mInputWrapper.setOriginText(text);
edit.addTextChangedListener(edit.mInputWrapper);
final InputMethodManager imm = (InputMethodManager) mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edit, 0);
}
}
break;
case HANDLER_CLOSE_IME_KEYBOARD:
{
GodotEditText edit = (GodotEditText) msg.obj;
edit.removeTextChangedListener(mInputWrapper);
final InputMethodManager imm = (InputMethodManager) mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
edit.mView.requestFocus();
}
break;
}
}
};
}
// ===========================================================
// Getter & Setter
// ===========================================================
public void setView(final GodotView view) {
this.mView = view;
if(mInputWrapper == null)
mInputWrapper = new GodotTextInputWrapper(mView, this);
this.setOnEditorActionListener(mInputWrapper);
view.requestFocus();
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
super.onKeyDown(keyCode, keyEvent);
/* Let GlSurfaceView get focus if back key is input. */
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.mView.requestFocus();
}
return true;
}
// ===========================================================
// Methods
// ===========================================================
public void showKeyboard(String p_existing_text) {
this.mOriginText = p_existing_text;
final Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
msg.obj = this;
sHandler.sendMessage(msg);
}
public void hideKeyboard() {
final Message msg = new Message();
msg.what = HANDLER_CLOSE_IME_KEYBOARD;
msg.obj = this;
sHandler.sendMessage(msg);
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}

View File

@@ -1,154 +0,0 @@
package com.android.godot.input;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.android.godot.*;
public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListener {
// ===========================================================
// Constants
// ===========================================================
private static final String TAG = GodotTextInputWrapper.class.getSimpleName();
// ===========================================================
// Fields
// ===========================================================
private final GodotView mView;
private final GodotEditText mEdit;
private String mText;
private String mOriginText;
// ===========================================================
// Constructors
// ===========================================================
public GodotTextInputWrapper(final GodotView view, final GodotEditText edit) {
this.mView = view;
this.mEdit = edit;
}
// ===========================================================
// Getter & Setter
// ===========================================================
private boolean isFullScreenEdit() {
final TextView textField = this.mEdit;
final InputMethodManager imm = (InputMethodManager) textField.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.isFullscreenMode();
}
public void setOriginText(final String originText) {
this.mOriginText = originText;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public void afterTextChanged(final Editable s) {
if (this.isFullScreenEdit()) {
return;
}
//if (BuildConfig.DEBUG) {
//Log.d(TAG, "afterTextChanged: " + s);
//}
int nModified = s.length() - this.mText.length();
if (nModified > 0) {
final String insertText = s.subSequence(this.mText.length(), s.length()).toString();
for(int i = 0; i < insertText.length(); i++) {
int ch = insertText.codePointAt(i);
GodotLib.key(0, ch, true);
GodotLib.key(0, ch, false);
}
/*
if (BuildConfig.DEBUG) {
Log.d(TAG, "insertText(" + insertText + ")");
}
*/
} else {
for (; nModified < 0; ++nModified) {
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
/*
if (BuildConfig.DEBUG) {
Log.d(TAG, "deleteBackward");
}
*/
}
}
this.mText = s.toString();
}
@Override
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
/*
if (BuildConfig.DEBUG) {
Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
}
*/
this.mText = pCharSequence.toString();
}
@Override
public void onTextChanged(final CharSequence pCharSequence, final int start, final int before, final int count) {
}
@Override
public boolean onEditorAction(final TextView pTextView, final int pActionID, final KeyEvent pKeyEvent) {
if (this.mEdit == pTextView && this.isFullScreenEdit()) {
// user press the action button, delete all old text and insert new text
for (int i = this.mOriginText.length(); i > 0; i--) {
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
/*
if (BuildConfig.DEBUG) {
Log.d(TAG, "deleteBackward");
}
*/
}
String text = pTextView.getText().toString();
/* If user input nothing, translate "\n" to engine. */
if (text.compareTo("") == 0) {
text = "\n";
}
if ('\n' != text.charAt(text.length() - 1)) {
text += '\n';
}
for(int i = 0; i < text.length(); i++) {
int ch = text.codePointAt(i);
GodotLib.key(0, ch, true);
GodotLib.key(0, ch, false);
}
/*
if (BuildConfig.DEBUG) {
Log.d(TAG, "insertText(" + insertText + ")");
}
*/
}
if (pActionID == EditorInfo.IME_ACTION_DONE) {
this.mView.requestFocus();
}
return false;
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}

View File

@@ -1,71 +0,0 @@
package com.android.godot.payments;
import com.android.vending.billing.IInAppBillingService;
import android.content.Context;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.util.Log;
abstract public class ConsumeTask {
private Context context;
private IInAppBillingService mService;
public ConsumeTask(IInAppBillingService mService, Context context ){
this.context = context;
this.mService = mService;
}
public void consume(final String sku){
// Log.d("XXX", "Consuming product " + sku);
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
String _token = pc.getConsumableValue("token", sku);
// Log.d("XXX", "token " + _token);
if(!isBlocked && _token == null){
// _token = "inapp:"+context.getPackageName()+":android.test.purchased";
// Log.d("XXX", "Consuming product " + sku + " with token " + _token);
}else if(!isBlocked){
// Log.d("XXX", "It is not blocked ¿?");
return;
}else if(_token == null){
// Log.d("XXX", "No token available");
this.error("No token for sku:" + sku);
return;
}
final String token = _token;
new AsyncTask<String, String, String>(){
@Override
protected String doInBackground(String... params) {
try {
// Log.d("XXX", "Requesting to release item.");
int response = mService.consumePurchase(3, context.getPackageName(), token);
// Log.d("XXX", "release response code: " + response);
if(response == 0 || response == 8){
return null;
}
} catch (RemoteException e) {
return e.getMessage();
}
return "Some error";
}
protected void onPostExecute(String param){
if(param == null){
success( new PaymentsCache(context).getConsumableValue("ticket", sku) );
}else{
error(param);
}
}
}.execute();
}
abstract protected void success(String ticket);
abstract protected void error(String message);
}

View File

@@ -1,53 +0,0 @@
package com.android.godot.payments;
import com.android.vending.billing.IInAppBillingService;
import android.content.Context;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.util.Log;
abstract public class GenericConsumeTask extends AsyncTask<String, String, String>{
private Context context;
private IInAppBillingService mService;
public GenericConsumeTask(Context context, IInAppBillingService mService, String sku, String receipt, String signature, String token){
this.context = context;
this.mService = mService;
this.sku = sku;
this.receipt = receipt;
this.signature = signature;
this.token = token;
}
private String sku;
private String receipt;
private String signature;
private String token;
@Override
protected String doInBackground(String... params) {
try {
// Log.d("godot", "Requesting to consume an item with token ." + token);
int response = mService.consumePurchase(3, context.getPackageName(), token);
// Log.d("godot", "consumePurchase response: " + response);
if(response == 0 || response == 8){
return null;
}
} catch (Exception e) {
Log.d("godot", "Error " + e.getClass().getName() + ":" + e.getMessage());
}
return null;
}
protected void onPostExecute(String sarasa){
onSuccess(sku, receipt, signature, token);
}
abstract public void onSuccess(String sku, String receipt, String signature, String token);
}

View File

@@ -1,82 +0,0 @@
package com.android.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.GodotLib;
import com.android.godot.utils.Crypt;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class HandlePurchaseTask {
private Activity context;
public HandlePurchaseTask(Activity context ){
this.context = context;
}
public void handlePurchaseRequest(int resultCode, Intent data){
// Log.d("XXX", "Handling purchase response");
// int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
PaymentsCache pc = new PaymentsCache(context);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
// Log.d("XXX", "Purchase data:" + purchaseData);
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
//Log.d("XXX", "Purchase signature:" + dataSignature);
if (resultCode == Activity.RESULT_OK) {
try {
// Log.d("SARLANGA", purchaseData);
JSONObject jo = new JSONObject(purchaseData);
// String sku = jo.getString("productId");
// alert("You have bought the " + sku + ". Excellent choice, aventurer!");
// String orderId = jo.getString("orderId");
// String packageName = jo.getString("packageName");
String productId = jo.getString("productId");
// Long purchaseTime = jo.getLong("purchaseTime");
// Integer state = jo.getInt("purchaseState");
String developerPayload = jo.getString("developerPayload");
String purchaseToken = jo.getString("purchaseToken");
if(! pc.getConsumableValue("validation_hash", productId).equals(developerPayload) ) {
error("Untrusted callback");
return;
}
// Log.d("XXX", "Este es el product ID:" + productId);
pc.setConsumableValue("ticket_signautre", productId, dataSignature);
pc.setConsumableValue("ticket", productId, purchaseData);
pc.setConsumableFlag("block", productId, true);
pc.setConsumableValue("token", productId, purchaseToken);
success(productId, dataSignature, purchaseData);
return;
} catch (JSONException e) {
error(e.getMessage());
}
}else if( resultCode == Activity.RESULT_CANCELED){
canceled();
}
}
abstract protected void success(String sku, String signature, String ticket);
abstract protected void error(String message);
abstract protected void canceled();
}

View File

@@ -1,45 +0,0 @@
package com.android.godot.payments;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
public class PaymentsCache {
public Context context;
public PaymentsCache(Context context){
this.context = context;
}
public void setConsumableFlag(String set, String sku, Boolean flag){
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(sku, flag);
editor.commit();
}
public boolean getConsumableFlag(String set, String sku){
SharedPreferences sharedPref = context.getSharedPreferences(
"consumables_" + set, Context.MODE_PRIVATE);
return sharedPref.getBoolean(sku, false);
}
public void setConsumableValue(String set, String sku, String value){
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(sku, value);
// Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
editor.commit();
}
public String getConsumableValue(String set, String sku){
SharedPreferences sharedPref = context.getSharedPreferences(
"consumables_" + set, Context.MODE_PRIVATE);
// Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
return sharedPref.getString(sku, null);
}
}

View File

@@ -1,282 +0,0 @@
package com.android.godot.payments;
import java.util.ArrayList;
import java.util.List;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import com.android.godot.Dictionary;
import com.android.godot.Godot;
import com.android.godot.GodotPaymentV3;
import com.android.vending.billing.IInAppBillingService;
public class PaymentsManager {
public static final int BILLING_RESPONSE_RESULT_OK = 0;
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
private static boolean auto_consume = true;
private Activity activity;
IInAppBillingService mService;
public void setActivity(Activity activity){
this.activity = activity;
}
public static PaymentsManager createManager(Activity activity){
PaymentsManager manager = new PaymentsManager(activity);
return manager;
}
private PaymentsManager(Activity activity){
this.activity = activity;
}
public PaymentsManager initService(){
Intent intent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
intent.setPackage("com.android.vending");
activity.bindService(
intent,
mServiceConn,
Context.BIND_AUTO_CREATE);
return this;
}
public void destroy(){
if (mService != null) {
activity.unbindService(mServiceConn);
}
}
ServiceConnection mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
};
public void requestPurchase(final String sku, String transactionId){
new PurchaseTask(mService, Godot.getInstance()) {
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
}
@Override
protected void alreadyOwned() {
godotPaymentV3.callbackAlreadyOwned(sku);
}
}.purchase(sku, transactionId);
}
public void consumeUnconsumedPurchases(){
new ReleaseAllConsumablesTask(mService, activity) {
@Override
protected void success(String sku, String receipt, String signature, String token) {
godotPaymentV3.callbackSuccessProductMassConsumed(receipt, signature, sku);
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
@Override
protected void notRequired() {
godotPaymentV3.callbackSuccessNoUnconsumedPurchases();
}
}.consumeItAll();
}
public void requestPurchased(){
try{
PaymentsCache pc = new PaymentsCache(Godot.getInstance());
// Log.d("godot", "requestPurchased for " + activity.getPackageName());
Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp",null);
/*
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
Log.d("godot", String.format("%s %s (%s)", key, value.toString(), value.getClass().getName()));
}
*/
if (bundle.getInt("RESPONSE_CODE") == 0){
final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
if (myPurchases == null || myPurchases.size() == 0){
// Log.d("godot", "No purchases!");
godotPaymentV3.callbackPurchased("", "", "");
return;
}
// Log.d("godot", "# products are purchased:" + myPurchases.size());
for (int i=0;i<myPurchases.size();i++)
{
try{
String receipt = myPurchases.get(i);
JSONObject inappPurchaseData = new JSONObject(receipt);
String sku = inappPurchaseData.getString("productId");
String token = inappPurchaseData.getString("purchaseToken");
String signature = mySignatures.get(i);
// Log.d("godot", "purchased item:" + token + "\n" + receipt);
pc.setConsumableValue("ticket_signautre", sku, signature);
pc.setConsumableValue("ticket", sku, receipt);
pc.setConsumableFlag("block", sku, true);
pc.setConsumableValue("token", sku, token);
godotPaymentV3.callbackPurchased(receipt, signature, sku);
} catch (JSONException e) {
}
}
}
}catch(Exception e){
Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage());
}
}
public void processPurchaseResponse(int resultCode, Intent data) {
new HandlePurchaseTask(activity){
@Override
protected void success(final String sku, final String signature, final String ticket) {
godotPaymentV3.callbackSuccess(ticket, signature, sku);
if (auto_consume){
new ConsumeTask(mService, activity) {
@Override
protected void success(String ticket) {
// godotPaymentV3.callbackSuccess("");
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
}.consume(sku);
}
// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
// godotPaymentV3.callbackSuccess(ticket);
//validatePurchase(purchaseToken, sku);
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
}
}.handlePurchaseRequest(resultCode, data);
}
public void validatePurchase(String purchaseToken, final String sku){
new ValidateTask(activity, godotPaymentV3){
@Override
protected void success() {
new ConsumeTask(mService, activity) {
@Override
protected void success(String ticket) {
godotPaymentV3.callbackSuccess(ticket, null, sku);
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
}.consume(sku);
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
}
}.validatePurchase(sku);
}
public void setAutoConsume(boolean autoConsume){
auto_consume = autoConsume;
}
public void consume(final String sku){
new ConsumeTask(mService, activity) {
@Override
protected void success(String ticket) {
godotPaymentV3.callbackSuccessProductMassConsumed(ticket, "", sku);
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
}.consume(sku);
}
private GodotPaymentV3 godotPaymentV3;
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
this.godotPaymentV3 = godotPaymentV3;
}
}

View File

@@ -1,101 +0,0 @@
package com.android.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.GodotLib;
import com.android.godot.utils.Crypt;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class PurchaseTask {
private Activity context;
private IInAppBillingService mService;
public PurchaseTask(IInAppBillingService mService, Activity context ){
this.context = context;
this.mService = mService;
}
private boolean isLooping = false;
public void purchase(final String sku, final String transactionId){
Log.d("XXX", "Starting purchase for: " + sku);
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
// if(isBlocked){
// Log.d("XXX", "Is awaiting payment confirmation");
// error("Awaiting payment confirmation");
// return;
// }
final String hash = transactionId;
Bundle buyIntentBundle;
try {
buyIntentBundle = mService.getBuyIntent(3, context.getApplicationContext().getPackageName(), sku, "inapp", hash );
} catch (RemoteException e) {
// Log.d("XXX", "Error: " + e.getMessage());
error(e.getMessage());
return;
}
Object rc = buyIntentBundle.get("RESPONSE_CODE");
int responseCode = 0;
if(rc == null){
responseCode = PaymentsManager.BILLING_RESPONSE_RESULT_OK;
}else if( rc instanceof Integer){
responseCode = ((Integer)rc).intValue();
}else if( rc instanceof Long){
responseCode = (int)((Long)rc).longValue();
}
// Log.d("XXX", "Buy intent response code: " + responseCode);
if(responseCode == 1 || responseCode == 3 || responseCode == 4){
canceled();
return;
}
if(responseCode == 7){
alreadyOwned();
return;
}
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
pc.setConsumableValue("validation_hash", sku, hash);
try {
if(context == null){
// Log.d("XXX", "No context!");
}
if(pendingIntent == null){
// Log.d("XXX", "No pending intent");
}
// Log.d("XXX", "Starting activity for purchase!");
context.startIntentSenderForResult(
pendingIntent.getIntentSender(),
PaymentsManager.REQUEST_CODE_FOR_PURCHASE,
new Intent(),
Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
} catch (SendIntentException e) {
error(e.getMessage());
}
}
abstract protected void error(String message);
abstract protected void canceled();
abstract protected void alreadyOwned();
}

View File

@@ -1,87 +0,0 @@
package com.android.godot.payments;
import java.util.ArrayList;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.Dictionary;
import com.android.godot.Godot;
import com.android.vending.billing.IInAppBillingService;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class ReleaseAllConsumablesTask {
private Context context;
private IInAppBillingService mService;
public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context ){
this.context = context;
this.mService = mService;
}
public void consumeItAll(){
try{
// Log.d("godot", "consumeItall for " + context.getPackageName());
Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp",null);
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
// Log.d("godot", String.format("%s %s (%s)", key,
// value.toString(), value.getClass().getName()));
}
if (bundle.getInt("RESPONSE_CODE") == 0){
final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
if (myPurchases == null || myPurchases.size() == 0){
// Log.d("godot", "No purchases!");
notRequired();
return;
}
// Log.d("godot", "# products to be consumed:" + myPurchases.size());
for (int i=0;i<myPurchases.size();i++)
{
try{
String receipt = myPurchases.get(i);
JSONObject inappPurchaseData = new JSONObject(receipt);
String sku = inappPurchaseData.getString("productId");
String token = inappPurchaseData.getString("purchaseToken");
String signature = mySignatures.get(i);
// Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
new GenericConsumeTask(context, mService, sku, receipt,signature, token) {
@Override
public void onSuccess(String sku, String receipt, String signature, String token) {
ReleaseAllConsumablesTask.this.success(sku, receipt, signature, token);
}
}.execute();
} catch (JSONException e) {
}
}
}
}catch(Exception e){
Log.d("godot", "Error releasing products:" + e.getClass().getName() + ":" + e.getMessage());
}
}
abstract protected void success(String sku, String receipt, String signature, String token);
abstract protected void error(String message);
abstract protected void notRequired();
}

View File

@@ -1,97 +0,0 @@
package com.android.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.Godot;
import com.android.godot.GodotLib;
import com.android.godot.GodotPaymentV3;
import com.android.godot.utils.Crypt;
import com.android.godot.utils.HttpRequester;
import com.android.godot.utils.RequestParams;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class ValidateTask {
private Activity context;
private GodotPaymentV3 godotPaymentsV3;
public ValidateTask(Activity context, GodotPaymentV3 godotPaymentsV3){
this.context = context;
this.godotPaymentsV3 = godotPaymentsV3;
}
public void validatePurchase(final String sku){
new AsyncTask<String, String, String>(){
private ProgressDialog dialog;
@Override
protected void onPreExecute(){
dialog = ProgressDialog.show(context, null, "Please wait...");
}
@Override
protected String doInBackground(String... params) {
PaymentsCache pc = new PaymentsCache(context);
String url = godotPaymentsV3.getPurchaseValidationUrlPrefix();
RequestParams param = new RequestParams();
param.setUrl(url);
param.put("ticket", pc.getConsumableValue("ticket", sku));
param.put("purchaseToken", pc.getConsumableValue("token", sku));
param.put("sku", sku);
// Log.d("XXX", "Haciendo request a " + url);
// Log.d("XXX", "ticket: " + pc.getConsumableValue("ticket", sku));
// Log.d("XXX", "purchaseToken: " + pc.getConsumableValue("token", sku));
// Log.d("XXX", "sku: " + sku);
param.put("package", context.getApplicationContext().getPackageName());
HttpRequester requester = new HttpRequester();
String jsonResponse = requester.post(param);
// Log.d("XXX", "Validation response:\n"+jsonResponse);
return jsonResponse;
}
@Override
protected void onPostExecute(String response){
if(dialog != null){
dialog.dismiss();
}
JSONObject j;
try {
j = new JSONObject(response);
if(j.getString("status").equals("OK")){
success();
return;
}else if(j.getString("status") != null){
error(j.getString("message"));
}else{
error("Connection error");
}
} catch (JSONException e) {
error(e.getMessage());
}catch (Exception e){
error(e.getMessage());
}
}
}.execute();
}
abstract protected void success();
abstract protected void error(String message);
abstract protected void canceled();
}

View File

@@ -1,39 +0,0 @@
package com.android.godot.utils;
import java.security.MessageDigest;
import java.util.Random;
public class Crypt {
public static String md5(String input){
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(input.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i=0; i<messageDigest.length; i++)
hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
return hexString.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static String createRandomHash(){
return md5(Long.toString(createRandomLong()));
}
public static long createAbsRandomLong(){
return Math.abs(createRandomLong());
}
public static long createRandomLong(){
Random r = new Random();
return r.nextLong();
}
}

View File

@@ -1,54 +0,0 @@
package com.android.godot.utils;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class CustomSSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}

View File

@@ -1,206 +0,0 @@
package com.android.godot.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class HttpRequester {
private Context context;
private static final int TTL = 600000; // 10 minutos
private long cttl=0;
public HttpRequester(){
// Log.d("XXX", "Creando http request sin contexto");
}
public HttpRequester(Context context){
this.context=context;
// Log.d("XXX", "Creando http request con contexto");
}
public String post(RequestParams params){
HttpPost httppost = new HttpPost(params.getUrl());
try {
httppost.setEntity(new UrlEncodedFormEntity(params.toPairsList()));
return request(httppost);
} catch (UnsupportedEncodingException e) {
return null;
}
}
public String get(RequestParams params){
String response = getResponseFromCache(params.getUrl());
if(response == null){
// Log.d("XXX", "Cache miss!");
HttpGet httpget = new HttpGet(params.getUrl());
long timeInit = new Date().getTime();
response = request(httpget);
long delay = new Date().getTime() - timeInit;
Log.d("com.app11tt.android.utils.HttpRequest::get(url)", "Url: " + params.getUrl() + " downloaded in " + String.format("%.03f", delay/1000.0f) + " seconds");
if(response == null || response.length() == 0){
response = "";
}else{
saveResponseIntoCache(params.getUrl(), response);
}
}
Log.d("XXX", "Req: " + params.getUrl());
Log.d("XXX", "Resp: " + response);
return response;
}
private String request(HttpUriRequest request){
// Log.d("XXX", "Haciendo request a: " + request.getURI() );
Log.d("PPP", "Haciendo request a: " + request.getURI() );
long init = new Date().getTime();
HttpClient httpclient = getNewHttpClient();
HttpParams httpParameters = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 0);
HttpConnectionParams.setSoTimeout(httpParameters, 0);
HttpConnectionParams.setTcpNoDelay(httpParameters, true);
try {
HttpResponse response = httpclient.execute(request);
Log.d("PPP", "Fin de request (" + (new Date().getTime() - init) + ") a: " + request.getURI() );
// Log.d("XXX1", "Status:" + response.getStatusLine().toString());
if(response.getStatusLine().getStatusCode() == 200){
String strResponse = EntityUtils.toString(response.getEntity());
// Log.d("XXX2", strResponse);
return strResponse;
}else{
Log.d("XXX3", "Response status code:" + response.getStatusLine().getStatusCode() + "\n" + EntityUtils.toString(response.getEntity()));
return null;
}
} catch (ClientProtocolException e) {
Log.d("XXX3", e.getMessage());
} catch (IOException e) {
Log.d("XXX4", e.getMessage());
}
return null;
}
private HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append((line + "\n"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public void saveResponseIntoCache(String request, String response){
if(context == null){
// Log.d("XXX", "No context, cache failed!");
return;
}
SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("request_" + Crypt.md5(request), response);
editor.putLong("request_" + Crypt.md5(request) + "_ttl", new Date().getTime() + getTtl());
editor.commit();
}
public String getResponseFromCache(String request){
if(context == null){
Log.d("XXX", "No context, cache miss");
return null;
}
SharedPreferences sharedPref = context.getSharedPreferences( "http_get_cache", Context.MODE_PRIVATE);
long ttl = getResponseTtl(request);
if(ttl == 0l || (new Date().getTime() - ttl) > 0l){
Log.d("XXX", "Cache invalid ttl:" + ttl + " vs now:" + new Date().getTime());
return null;
}
return sharedPref.getString("request_" + Crypt.md5(request), null);
}
public long getResponseTtl(String request){
SharedPreferences sharedPref = context.getSharedPreferences(
"http_get_cache", Context.MODE_PRIVATE);
return sharedPref.getLong("request_" + Crypt.md5(request) + "_ttl", 0l);
}
public long getTtl() {
return cttl > 0 ? cttl : TTL;
}
public void setTtl(long ttl) {
this.cttl = (ttl*1000) + new Date().getTime();
}
}

View File

@@ -1,58 +0,0 @@
package com.android.godot.utils;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class RequestParams {
private HashMap<String,String> params;
private String url;
public RequestParams(){
params = new HashMap<String,String>();
}
public void put(String key, String value){
params.put(key, value);
}
public String get(String key){
return params.get(key);
}
public void remove(Object key){
params.remove(key);
}
public boolean has(String key){
return params.containsKey(key);
}
public List<NameValuePair> toPairsList(){
List<NameValuePair> fields = new ArrayList<NameValuePair>();
for(String key : params.keySet()){
fields.add(new BasicNameValuePair(key, this.get(key)));
}
return fields;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}