From 40ba22631bbb7fc4c6b88d01402e132dbaceaf2b Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 8 Jan 2016 17:53:00 -0300 Subject: Renamed godot domain from com.android.godot (which was incorrect) to org.godotengine.godot --- .../java/src/com/android/godot/Dictionary.java | 80 -- .../android/java/src/com/android/godot/Godot.java | 925 --------------------- .../godot/GodotDownloaderAlarmReceiver.java | 30 - .../com/android/godot/GodotDownloaderService.java | 56 -- .../java/src/com/android/godot/GodotIO.java | 673 --------------- .../java/src/com/android/godot/GodotLib.java | 66 -- .../java/src/com/android/godot/GodotPaymentV3.java | 154 ---- .../java/src/com/android/godot/GodotView.java | 661 --------------- .../src/com/android/godot/input/GodotEditText.java | 133 --- .../android/godot/input/GodotTextInputWrapper.java | 154 ---- .../com/android/godot/payments/ConsumeTask.java | 71 -- .../android/godot/payments/GenericConsumeTask.java | 53 -- .../android/godot/payments/HandlePurchaseTask.java | 82 -- .../com/android/godot/payments/PaymentsCache.java | 45 - .../android/godot/payments/PaymentsManager.java | 282 ------- .../com/android/godot/payments/PurchaseTask.java | 101 --- .../godot/payments/ReleaseAllConsumablesTask.java | 87 -- .../com/android/godot/payments/ValidateTask.java | 97 --- .../java/src/com/android/godot/utils/Crypt.java | 39 - .../godot/utils/CustomSSLSocketFactory.java | 54 -- .../src/com/android/godot/utils/HttpRequester.java | 206 ----- .../src/com/android/godot/utils/RequestParams.java | 58 -- .../java/src/org/godotengine/godot/Dictionary.java | 80 ++ .../java/src/org/godotengine/godot/Godot.java | 925 +++++++++++++++++++++ .../godot/GodotDownloaderAlarmReceiver.java | 30 + .../godotengine/godot/GodotDownloaderService.java | 56 ++ .../java/src/org/godotengine/godot/GodotIO.java | 673 +++++++++++++++ .../java/src/org/godotengine/godot/GodotLib.java | 66 ++ .../src/org/godotengine/godot/GodotPaymentV3.java | 154 ++++ .../java/src/org/godotengine/godot/GodotView.java | 661 +++++++++++++++ .../org/godotengine/godot/input/GodotEditText.java | 133 +++ .../godot/input/GodotTextInputWrapper.java | 154 ++++ .../godotengine/godot/payments/ConsumeTask.java | 71 ++ .../godot/payments/GenericConsumeTask.java | 53 ++ .../godot/payments/HandlePurchaseTask.java | 82 ++ .../godotengine/godot/payments/PaymentsCache.java | 45 + .../godot/payments/PaymentsManager.java | 282 +++++++ .../godotengine/godot/payments/PurchaseTask.java | 101 +++ .../godot/payments/ReleaseAllConsumablesTask.java | 87 ++ .../godotengine/godot/payments/ValidateTask.java | 97 +++ .../src/org/godotengine/godot/utils/Crypt.java | 39 + .../godot/utils/CustomSSLSocketFactory.java | 54 ++ .../org/godotengine/godot/utils/HttpRequester.java | 206 +++++ .../org/godotengine/godot/utils/RequestParams.java | 58 ++ 44 files changed, 4107 insertions(+), 4107 deletions(-) delete mode 100644 platform/android/java/src/com/android/godot/Dictionary.java delete mode 100644 platform/android/java/src/com/android/godot/Godot.java delete mode 100644 platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java delete mode 100644 platform/android/java/src/com/android/godot/GodotDownloaderService.java delete mode 100644 platform/android/java/src/com/android/godot/GodotIO.java delete mode 100644 platform/android/java/src/com/android/godot/GodotLib.java delete mode 100644 platform/android/java/src/com/android/godot/GodotPaymentV3.java delete mode 100644 platform/android/java/src/com/android/godot/GodotView.java delete mode 100644 platform/android/java/src/com/android/godot/input/GodotEditText.java delete mode 100644 platform/android/java/src/com/android/godot/input/GodotTextInputWrapper.java delete mode 100644 platform/android/java/src/com/android/godot/payments/ConsumeTask.java delete mode 100644 platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java delete mode 100644 platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java delete mode 100644 platform/android/java/src/com/android/godot/payments/PaymentsCache.java delete mode 100644 platform/android/java/src/com/android/godot/payments/PaymentsManager.java delete mode 100644 platform/android/java/src/com/android/godot/payments/PurchaseTask.java delete mode 100644 platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java delete mode 100644 platform/android/java/src/com/android/godot/payments/ValidateTask.java delete mode 100644 platform/android/java/src/com/android/godot/utils/Crypt.java delete mode 100644 platform/android/java/src/com/android/godot/utils/CustomSSLSocketFactory.java delete mode 100644 platform/android/java/src/com/android/godot/utils/HttpRequester.java delete mode 100644 platform/android/java/src/com/android/godot/utils/RequestParams.java create mode 100644 platform/android/java/src/org/godotengine/godot/Dictionary.java create mode 100644 platform/android/java/src/org/godotengine/godot/Godot.java create mode 100644 platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java create mode 100644 platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java create mode 100644 platform/android/java/src/org/godotengine/godot/GodotIO.java create mode 100644 platform/android/java/src/org/godotengine/godot/GodotLib.java create mode 100644 platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java create mode 100644 platform/android/java/src/org/godotengine/godot/GodotView.java create mode 100644 platform/android/java/src/org/godotengine/godot/input/GodotEditText.java create mode 100644 platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java create mode 100644 platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java create mode 100644 platform/android/java/src/org/godotengine/godot/utils/Crypt.java create mode 100644 platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java create mode 100644 platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java create mode 100644 platform/android/java/src/org/godotengine/godot/utils/RequestParams.java (limited to 'platform/android/java/src') diff --git a/platform/android/java/src/com/android/godot/Dictionary.java b/platform/android/java/src/com/android/godot/Dictionary.java deleted file mode 100644 index 4ed12f5818..0000000000 --- a/platform/android/java/src/com/android/godot/Dictionary.java +++ /dev/null @@ -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 { - - protected String[] keys_cache; - - public String[] get_keys() { - - String[] ret = new String[size()]; - int i=0; - Set 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 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; - }; -}; diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java deleted file mode 100644 index 4c5a313576..0000000000 --- a/platform/android/java/src/com/android/godot/Godot.java +++ /dev/null @@ -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 ptr = new ArrayList(); - - 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 singletons = new ArrayList(); - 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;i65535) { - 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 new_args = new LinkedList(); - - - for(int i=0;i= 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= 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 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= 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)); - - } - -} diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java deleted file mode 100644 index e82c3eb0fe..0000000000 --- a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java +++ /dev/null @@ -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: - * - */ -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()); - } - } -} diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderService.java b/platform/android/java/src/com/android/godot/GodotDownloaderService.java deleted file mode 100644 index 2657edc1d2..0000000000 --- a/platform/android/java/src/com/android/godot/GodotDownloaderService.java +++ /dev/null @@ -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(); - } - -} diff --git a/platform/android/java/src/com/android/godot/GodotIO.java b/platform/android/java/src/com/android/godot/GodotIO.java deleted file mode 100644 index a7dc0c2f75..0000000000 --- a/platform/android/java/src/com/android/godot/GodotIO.java +++ /dev/null @@ -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 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 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(); - dirs=new HashMap(); - 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; - } - -} diff --git a/platform/android/java/src/com/android/godot/GodotLib.java b/platform/android/java/src/com/android/godot/GodotLib.java deleted file mode 100644 index 3d870b3b1f..0000000000 --- a/platform/android/java/src/com/android/godot/GodotLib.java +++ /dev/null @@ -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); - -} diff --git a/platform/android/java/src/com/android/godot/GodotPaymentV3.java b/platform/android/java/src/com/android/godot/GodotPaymentV3.java deleted file mode 100644 index 0799e1e83d..0000000000 --- a/platform/android/java/src/com/android/godot/GodotPaymentV3.java +++ /dev/null @@ -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); - } -} - diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java deleted file mode 100644 index bc249d46c6..0000000000 --- a/platform/android/java/src/com/android/godot/GodotView.java +++ /dev/null @@ -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 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 - // =========================================================== -} diff --git a/platform/android/java/src/com/android/godot/payments/ConsumeTask.java b/platform/android/java/src/com/android/godot/payments/ConsumeTask.java deleted file mode 100644 index c983960770..0000000000 --- a/platform/android/java/src/com/android/godot/payments/ConsumeTask.java +++ /dev/null @@ -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(){ - - @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); - -} diff --git a/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java b/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java deleted file mode 100644 index d68f029246..0000000000 --- a/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java +++ /dev/null @@ -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{ - - 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); - -} diff --git a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java deleted file mode 100644 index 4c31704cc8..0000000000 --- a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java +++ /dev/null @@ -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(); - - -} diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java b/platform/android/java/src/com/android/godot/payments/PaymentsCache.java deleted file mode 100644 index 1de772bf28..0000000000 --- a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java +++ /dev/null @@ -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); - } - -} diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java deleted file mode 100644 index 189f7108c1..0000000000 --- a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java +++ /dev/null @@ -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 myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); - final ArrayList 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 = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); - final ArrayList 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(){ - - - 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(); - - -} diff --git a/platform/android/java/src/com/android/godot/utils/Crypt.java b/platform/android/java/src/com/android/godot/utils/Crypt.java deleted file mode 100644 index 7801f474b9..0000000000 --- a/platform/android/java/src/com/android/godot/utils/Crypt.java +++ /dev/null @@ -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 - */ -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(); - } -} \ No newline at end of file diff --git a/platform/android/java/src/com/android/godot/utils/HttpRequester.java b/platform/android/java/src/com/android/godot/utils/HttpRequester.java deleted file mode 100644 index 7de77881d0..0000000000 --- a/platform/android/java/src/com/android/godot/utils/HttpRequester.java +++ /dev/null @@ -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 - */ -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(); - } - -} diff --git a/platform/android/java/src/com/android/godot/utils/RequestParams.java b/platform/android/java/src/com/android/godot/utils/RequestParams.java deleted file mode 100644 index 31bf1940ad..0000000000 --- a/platform/android/java/src/com/android/godot/utils/RequestParams.java +++ /dev/null @@ -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 - */ -public class RequestParams { - - private HashMap params; - private String url; - - public RequestParams(){ - params = new HashMap(); - } - - 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 toPairsList(){ - List fields = new ArrayList(); - - 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; - } - - -} diff --git a/platform/android/java/src/org/godotengine/godot/Dictionary.java b/platform/android/java/src/org/godotengine/godot/Dictionary.java new file mode 100644 index 0000000000..34051c4bb8 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/Dictionary.java @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* 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 org.godotengine.godot; + +import java.util.HashMap; +import java.util.Set; + + +public class Dictionary extends HashMap { + + protected String[] keys_cache; + + public String[] get_keys() { + + String[] ret = new String[size()]; + int i=0; + Set 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 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; + }; +}; diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java new file mode 100644 index 0000000000..6aa5d24f1c --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -0,0 +1,925 @@ +/*************************************************************************/ +/* 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 org.godotengine.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 org.godotengine.godot.payments.PaymentsManager; + +import java.io.IOException; + +import android.provider.Settings.Secure; +import android.widget.FrameLayout; + +import org.godotengine.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 ptr = new ArrayList(); + + 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 singletons = new ArrayList(); + 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;i65535) { + 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 new_args = new LinkedList(); + + + for(int i=0;i= 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= 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 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= 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)); + + } + +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java new file mode 100644 index 0000000000..b602f4757c --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java @@ -0,0 +1,30 @@ +package org.godotengine.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: + * + */ +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()); + } + } +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java new file mode 100644 index 0000000000..6735d387f3 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java @@ -0,0 +1,56 @@ +package org.godotengine.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(); + } + +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java new file mode 100644 index 0000000000..071d090e8b --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java @@ -0,0 +1,673 @@ +/*************************************************************************/ +/* 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 org.godotengine.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 org.godotengine.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 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 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(); + dirs=new HashMap(); + 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; + } + +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java new file mode 100644 index 0000000000..ddbcf2e5c6 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java @@ -0,0 +1,66 @@ +/*************************************************************************/ +/* 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 org.godotengine.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); + +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java new file mode 100644 index 0000000000..6bec49410d --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java @@ -0,0 +1,154 @@ +package org.godotengine.godot; + +import org.godotengine.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); + } +} + diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java new file mode 100644 index 0000000000..04b5dfa5dd --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotView.java @@ -0,0 +1,661 @@ +/*************************************************************************/ +/* 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 org.godotengine.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 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 + // =========================================================== +} diff --git a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java new file mode 100644 index 0000000000..61ccb97161 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java @@ -0,0 +1,71 @@ +package org.godotengine.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(){ + + @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); + +} diff --git a/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java new file mode 100644 index 0000000000..293e903284 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java @@ -0,0 +1,53 @@ +package org.godotengine.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{ + + 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); + +} diff --git a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java new file mode 100644 index 0000000000..d120551e4a --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java @@ -0,0 +1,82 @@ +package org.godotengine.godot.payments; + +import org.json.JSONException; +import org.json.JSONObject; + +import org.godotengine.godot.GodotLib; +import org.godotengine.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(); + + +} diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java new file mode 100644 index 0000000000..5f3d931593 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java @@ -0,0 +1,45 @@ +package org.godotengine.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); + } + +} diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java new file mode 100644 index 0000000000..effb58aa35 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java @@ -0,0 +1,282 @@ +package org.godotengine.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 org.godotengine.godot.Dictionary; +import org.godotengine.godot.Godot; +import org.godotengine.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 myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); + final ArrayList 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 = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); + final ArrayList 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(){ + + + 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(); + + +} diff --git a/platform/android/java/src/org/godotengine/godot/utils/Crypt.java b/platform/android/java/src/org/godotengine/godot/utils/Crypt.java new file mode 100644 index 0000000000..2fb81cef8c --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/utils/Crypt.java @@ -0,0 +1,39 @@ +package org.godotengine.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 + */ +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(); + } +} \ No newline at end of file diff --git a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java new file mode 100644 index 0000000000..14346702cc --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java @@ -0,0 +1,206 @@ +package org.godotengine.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 + */ +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(); + } + +} diff --git a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java new file mode 100644 index 0000000000..36753e368c --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java @@ -0,0 +1,58 @@ +package org.godotengine.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 + */ +public class RequestParams { + + private HashMap params; + private String url; + + public RequestParams(){ + params = new HashMap(); + } + + 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 toPairsList(){ + List fields = new ArrayList(); + + 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; + } + + +} -- cgit v1.2.3