diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-08-01 22:10:38 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-08-01 22:10:38 -0300 |
commit | 678948068bbde7f12a9c5f28a467b6cf4d127851 (patch) | |
tree | 75572f3a5cc6089a6ca3046e9307d0a7c0b72c51 /platform/android/java | |
parent | 9ff6d55822647c87eef392147ea15641d0922d47 (diff) |
Small Issues & Maintenance
-=-=-=-=-=-=-=-=-=-=-=-=-=
-Begin work on Navigation Meshes (simple pathfinding for now, will improve soon)
-More doc on theme overriding
-Upgraded OpenSSL to version without bugs
-Misc bugfixes
Diffstat (limited to 'platform/android/java')
11 files changed, 714 insertions, 103 deletions
diff --git a/platform/android/java/res/layout/downloading_expansion.xml b/platform/android/java/res/layout/downloading_expansion.xml new file mode 100644 index 0000000000..553155dcd3 --- /dev/null +++ b/platform/android/java/res/layout/downloading_expansion.xml @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="0" + android:orientation="vertical" > + + <TextView + android:id="@+id/statusText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="10dp" + android:layout_marginLeft="5dp" + android:layout_marginTop="10dp" + android:textStyle="bold" /> + + <LinearLayout + android:id="@+id/downloaderDashboard" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_below="@id/statusText" + android:orientation="vertical" > + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" > + + <TextView + android:id="@+id/progressAsFraction" + style="@android:style/TextAppearance.Small" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_marginLeft="5dp" + android:text="0MB / 0MB" > + </TextView> + + <TextView + android:id="@+id/progressAsPercentage" + style="@android:style/TextAppearance.Small" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignRight="@+id/progressBar" + android:text="0%" /> + + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/progressAsFraction" + android:layout_marginBottom="10dp" + android:layout_marginLeft="10dp" + android:layout_marginRight="10dp" + android:layout_marginTop="10dp" + android:layout_weight="1" /> + + <TextView + android:id="@+id/progressAverageSpeed" + style="@android:style/TextAppearance.Small" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_below="@+id/progressBar" + android:layout_marginLeft="5dp" /> + + <TextView + android:id="@+id/progressTimeRemaining" + style="@android:style/TextAppearance.Small" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignRight="@+id/progressBar" + android:layout_below="@+id/progressBar" /> + </RelativeLayout> + + <LinearLayout + android:id="@+id/downloaderDashboard" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + + <Button + android:id="@+id/pauseButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginBottom="10dp" + android:layout_marginLeft="10dp" + android:layout_marginRight="5dp" + android:layout_marginTop="10dp" + android:layout_weight="0" + android:minHeight="40dp" + android:minWidth="94dp" + android:text="@string/text_button_pause" /> + + <Button + android:id="@+id/cancelButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginBottom="10dp" + android:layout_marginLeft="5dp" + android:layout_marginRight="5dp" + android:layout_marginTop="10dp" + android:layout_weight="0" + android:minHeight="40dp" + android:minWidth="94dp" + android:text="@string/text_button_cancel" + android:visibility="gone" /> + </LinearLayout> + </LinearLayout> + </LinearLayout> + + <LinearLayout + android:id="@+id/approveCellular" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1" + android:orientation="vertical" + android:visibility="gone" > + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp" + android:id="@+id/textPausedParagraph1" + android:text="@string/text_paused_cellular" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp" + android:id="@+id/textPausedParagraph2" + android:text="@string/text_paused_cellular_2" /> + + <LinearLayout + android:id="@+id/buttonRow" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + + <Button + android:id="@+id/resumeOverCellular" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_margin="10dp" + android:text="@string/text_button_resume_cellular" /> + + <Button + android:id="@+id/wifiSettingsButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_margin="10dp" + android:text="@string/text_button_wifi_settings" /> + </LinearLayout> + </LinearLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/platform/android/java/res/values/strings.xml b/platform/android/java/res/values/strings.xml index 3a38d40599..49ebcc06f9 100644 --- a/platform/android/java/res/values/strings.xml +++ b/platform/android/java/res/values/strings.xml @@ -3,5 +3,15 @@ <string name="godot_project_name_string">godot-project-name</string> <string name="testuf8">元気です</string> <string name="testuf2">元気です元気です元気です</string> - + <string name="text_paused_cellular">Would you like to enable downloading over cellular connections? Depending on your data plan, this may cost you money.</string> + <string name="text_paused_cellular_2">If you choose not to enable downloading over cellular connections, the download will automatically resume when wi-fi is available.</string> + <string name="text_button_resume_cellular">Resume download</string> + <string name="text_button_wifi_settings">Wi-Fi settings</string> + <string name="text_verifying_download">Verifying Download</string> + <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string> + <string name="text_validation_failed">XAPK File Validation Failed.</string> + <string name="text_button_pause">Pause Download</string> + <string name="text_button_resume">Resume Download</string> + <string name="text_button_cancel">Cancel</string> + <string name="text_button_cancel_verify">Cancel Verification</string> </resources> diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index 658c272321..57b0943a85 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -28,16 +28,20 @@ /*************************************************************************/ 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.*; @@ -48,33 +52,82 @@ 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 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; -public class Godot extends Activity implements SensorEventListener +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 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); @@ -83,20 +136,20 @@ public class Godot extends Activity implements SensorEventListener Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { boolean found=false; - System.out.printf("METHOD: %s\n",method.getName()); + Log.d("XXX","METHOD: %s\n" + method.getName()); for (String s : p_methods) { - System.out.printf("METHOD CMP WITH: %s\n",s); + Log.d("XXX", "METHOD CMP WITH: %s\n" + s); if (s.equals(method.getName())) { found=true; - System.out.printf("METHOD CMP VALID"); + Log.d("XXX","METHOD CMP VALID"); break; } } if (!found) continue; - System.out.printf("METHOD FOUND: %s\n",method.getName()); + Log.d("XXX","METHOD FOUND: %s\n" + method.getName()); List<String> ptr = new ArrayList<String>(); @@ -230,7 +283,7 @@ public class Godot extends Activity implements SensorEventListener byte[] len = new byte[4]; int r = is.read(len); if (r<4) { - System.out.printf("**ERROR** Wrong cmdline length.\n"); + Log.d("XXX","**ERROR** Wrong cmdline length.\n"); Log.d("GODOT", "**ERROR** Wrong cmdline length.\n"); return new String[0]; } @@ -258,7 +311,6 @@ public class Godot extends Activity implements SensorEventListener return cmdline; } catch (Exception e) { e.printStackTrace(); - System.out.printf("**ERROR** No commandline.\n"); Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage()); return new String[0]; } @@ -277,12 +329,14 @@ public class Godot extends Activity implements SensorEventListener String[] new_cmdline; int cll=0; if (command_line!=null) { + Log.d("GODOT", "initializeGodot: command_line: is not null" ); new_cmdline = new String[ command_line.length + 2 ]; cll=command_line.length; for(int i=0;i<command_line.length;i++) { new_cmdline[i]=command_line[i]; } } else { + Log.d("GODOT", "initializeGodot: command_line: is null" ); new_cmdline = new String[ 2 ]; } @@ -294,6 +348,13 @@ public class Godot extends Activity implements SensorEventListener io = new GodotIO(this); io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); GodotLib.io=io; + Log.d("GODOT", "command_line is null? " + ((command_line == null)?"yes":"no")); + if(command_line != null){ + Log.d("GODOT", "Command Line:"); + for(int w=0;w <command_line.length;w++){ + Log.d("GODOT"," " + command_line[w]); + } + } GodotLib.initialize(this,io.needsReloadHooks(),command_line); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); @@ -306,10 +367,16 @@ public class Godot extends Activity implements SensorEventListener } + @Override + public void onServiceConnected(Messenger m) { + mRemoteService = DownloaderServiceMarshaller.CreateProxy(m); + mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger()); + } - @Override protected void onCreate(Bundle icicle) { + @Override + protected void onCreate(Bundle icicle) { - System.out.printf("** GODOT ACTIVITY CREATED HERE ***\n"); + Log.d("GODOT", "** GODOT ACTIVITY CREATED HERE ***\n"); super.onCreate(icicle); _self = this; @@ -319,7 +386,8 @@ public class Godot extends Activity implements SensorEventListener //check for apk expansion API - if (!true) { + if (true) { + boolean md5mismatch = false; command_line = getCommandLine(); boolean use_apk_expansion=false; String main_pack_md5=null; @@ -338,17 +406,25 @@ public class Godot extends Activity implements SensorEventListener 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()) + if (new_args.isEmpty()){ + Log.d("GODOT", "new_args is empty"); command_line=null; - else + }else{ + Log.d("GODOT", "new_args is not empty"); command_line = new_args.toArray(new String[new_args.size()]); - + Log.d("GODOT", "command line is null? " + ( (command_line == null) ? "yes":"no")); + } if (use_apk_expansion && main_pack_md5!=null && main_pack_key!=null) { //check that environment is ok! if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED )) { @@ -374,49 +450,62 @@ public class Godot extends Activity implements SensorEventListener pack_valid=false; Log.d("GODOT","**PACK** - File does not exist"); - } else { - try { - - InputStream fis = new FileInputStream(expansion_pack_path); - - // Create MD5 Hash - byte[] buffer = new byte[16384]; - - MessageDigest complete = MessageDigest.getInstance("MD5"); - int numRead; - do { - numRead = fis.read(buffer); - if (numRead > 0) { - complete.update(buffer, 0, numRead); - } - } while (numRead != -1); - - - fis.close(); - byte[] messageDigest = complete.digest(); - - // Create Hex String - StringBuffer hexString = new StringBuffer(); - for (int i=0; i<messageDigest.length; i++) - hexString.append(Integer.toHexString(0xFF & messageDigest[i])); - String md5str = hexString.toString(); - - Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5); - if (!hexString.equals(main_pack_md5)) { - pack_valid=false; - } - } catch (Exception e) { - e.printStackTrace(); - Log.d("GODOT","**PACK FAIL**"); - pack_valid=false; + } 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", "Tengo que bajarme el apk"); + + 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", "INICIANDO DOWNLOAD SERVICE"); + 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()); + } } @@ -431,6 +520,7 @@ public class Godot extends Activity implements SensorEventListener } + @Override protected void onDestroy(){ if(mPaymentsManager != null ) mPaymentsManager.destroy(); @@ -442,8 +532,12 @@ public class Godot extends Activity implements SensorEventListener @Override protected void onPause() { super.onPause(); - if (!godot_initialized) + if (!godot_initialized){ + if (null != mDownloaderClientStub) { + mDownloaderClientStub.disconnect(this); + } return; + } mView.onPause(); mSensorManager.unregisterListener(this); GodotLib.focusout(); @@ -455,8 +549,12 @@ public class Godot extends Activity implements SensorEventListener @Override protected void onResume() { super.onResume(); - if (!godot_initialized) + if (!godot_initialized){ + if (null != mDownloaderClientStub) { + mDownloaderClientStub.connect(this); + } return; + } mView.onResume(); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); @@ -466,6 +564,8 @@ public class Godot extends Activity implements SensorEventListener singletons[i].onMainResume(); } + + } @@ -508,6 +608,54 @@ public class Godot extends Activity implements SensorEventListener } + + private boolean obbIsCorrupted(String f, String main_pack_md5){ + + try { + + InputStream fis = new FileInputStream(f); + + // Create MD5 Hash + byte[] buffer = new byte[16384]; + + MessageDigest complete = MessageDigest.getInstance("MD5"); + int numRead; + do { + numRead = fis.read(buffer); + if (numRead > 0) { + complete.update(buffer, 0, numRead); + } + } while (numRead != -1); + + + fis.close(); + byte[] messageDigest = complete.digest(); + + // Create Hex String + StringBuffer hexString = new StringBuffer(); + for (int i=0; i<messageDigest.length; i++) { + String s = Integer.toHexString(0xFF & messageDigest[i]); + + if (s.length()==1) { + s="0"+s; + } + hexString.append(s); + } + String md5str = hexString.toString(); + + //Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5); + if (!md5str.equals(main_pack_md5)) { + Log.d("GODOT","**PACK MD5 MISMATCH???** - MD5 Found: "+md5str+" "+Integer.toString(md5str.length())+" - MD5 Expected: "+main_pack_md5+" "+Integer.toString(main_pack_md5.length())); + return true; + } + return false; + } catch (Exception e) { + e.printStackTrace(); + Log.d("GODOT","**PACK FAIL**"); + return true; + } + } + //@Override public boolean dispatchTouchEvent (MotionEvent event) { public boolean gotTouchEvent(MotionEvent event) { @@ -602,5 +750,115 @@ public class Godot extends Activity implements SensorEventListener // 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 index d945a8b192..e82c3eb0fe 100644 --- a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java +++ b/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java @@ -6,6 +6,7 @@ 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 @@ -18,10 +19,12 @@ 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 index e0fe95ad96..2657edc1d2 100644 --- a/platform/android/java/src/com/android/godot/GodotDownloaderService.java +++ b/platform/android/java/src/com/android/godot/GodotDownloaderService.java @@ -1,5 +1,9 @@ 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; /** @@ -21,7 +25,11 @@ public class GodotDownloaderService extends DownloaderService { */ @Override public String getPublicKey() { - return BASE64_PUBLIC_KEY; + 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; } /** @@ -41,7 +49,8 @@ public class GodotDownloaderService extends DownloaderService { */ @Override public String getAlarmReceiverClassName() { - return GodotDownloaderAlarmReceiver.class.getName(); + Log.d("GODOT", "getAlarmReceiverClassName()"); + return GodotDownloaderAlarmReceiver.class.getName(); } } diff --git a/platform/android/java/src/com/android/godot/GodotPaymentV3.java b/platform/android/java/src/com/android/godot/GodotPaymentV3.java index dba4a9a774..a459f8e15c 100644 --- a/platform/android/java/src/com/android/godot/GodotPaymentV3.java +++ b/platform/android/java/src/com/android/godot/GodotPaymentV3.java @@ -1,8 +1,6 @@ package com.android.godot; - -import org.json.JSONObject; - +import com.android.godot.Dictionary; import android.app.Activity; import android.util.Log; @@ -44,10 +42,20 @@ public class GodotPaymentV3 extends Godot.SingletonBase { public GodotPaymentV3(Activity p_activity) { - registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature"}); + registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases"}); 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(){ @@ -56,9 +64,19 @@ public class GodotPaymentV3 extends Godot.SingletonBase { public void callbackSuccess(String ticket, String signature){ - Log.d(this.getClass().getName(), "PRE-Send callback to purchase success"); - GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature}); - Log.d(this.getClass().getName(), "POST-Send callback to purchase success"); + Log.d(this.getClass().getName(), "PRE-Send callback to purchase success"); + GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature}); + 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"); + 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(){ diff --git a/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java b/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java new file mode 100644 index 0000000000..88cf28798e --- /dev/null +++ b/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java @@ -0,0 +1,53 @@ +package com.android.godot.payments; + +import com.android.vending.billing.IInAppBillingService; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.RemoteException; +import android.util.Log; + +abstract public class GenericConsumeTask extends AsyncTask<String, String, String>{ + + private Context context; + private IInAppBillingService mService; + + + + + public GenericConsumeTask(Context context, IInAppBillingService mService, String sku, String receipt, String signature, String token){ + this.context = context; + this.mService = mService; + this.sku = sku; + this.receipt = receipt; + this.signature = signature; + this.token = token; + } + + private String sku; + private String receipt; + private String signature; + private String token; + + @Override + protected String doInBackground(String... params) { + try { + Log.d("godot", "Requesting to consume an item with token ." + token); + int response = mService.consumePurchase(3, context.getPackageName(), token); + Log.d("godot", "consumePurchase response: " + response); + if(response == 0 || response == 8){ + return null; + } + } catch (Exception e) { + Log.d("godot", "Error " + e.getClass().getName() + ":" + e.getMessage()); + } + return null; + } + + protected void onPostExecute(String sarasa){ + onSuccess(sku, receipt, signature, token); + } + + abstract public void onSuccess(String sku, String receipt, String signature, String token); + +} diff --git a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java index a810ac40ae..24eec9f30b 100644 --- a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java +++ b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java @@ -64,7 +64,7 @@ abstract public class HandlePurchaseTask { pc.setConsumableFlag("block", productId, true); pc.setConsumableValue("token", productId, purchaseToken); - success(productId, dataSignature); + success(productId, dataSignature, purchaseData); return; } catch (JSONException e) { error(e.getMessage()); @@ -74,7 +74,7 @@ abstract public class HandlePurchaseTask { } } - abstract protected void success(String ticket, String signature); + 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/PaymentsManager.java b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java index d85a8ea8ea..fd1a62738a 100644 --- a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java +++ b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java @@ -1,5 +1,9 @@ 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; @@ -7,7 +11,13 @@ 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; @@ -23,7 +33,6 @@ public class PaymentsManager { private Activity activity; IInAppBillingService mService; - public void setActivity(Activity activity){ this.activity = activity; } @@ -81,18 +90,39 @@ public class PaymentsManager { } + 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 processPurchaseResponse(int resultCode, Intent data) { new HandlePurchaseTask(activity){ @Override - protected void success(final String sku, final String signature) { + protected void success(final String sku, final String signature, final String ticket) { + godotPaymentV3.callbackSuccess(ticket, signature); new ConsumeTask(mService, activity) { @Override protected void success(String ticket) { // godotPaymentV3.callbackSuccess(""); - Log.d("XXX", "calling success:" + signature); - godotPaymentV3.callbackSuccess(ticket, signature); } @Override @@ -103,7 +133,7 @@ public class PaymentsManager { }.consume(sku); - +// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature); // godotPaymentV3.callbackSuccess(ticket); //validatePurchase(purchaseToken, sku); } @@ -166,5 +196,6 @@ public class PaymentsManager { this.godotPaymentV3 = godotPaymentV3; } + } diff --git a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java index 0856b4e900..75662a442e 100644 --- a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java +++ b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java @@ -64,31 +64,7 @@ abstract public class PurchaseTask { canceled(); return ; } - if(responseCode == 7){ - new ConsumeTask(mService, context) { - - @Override - protected void success(String ticket) { -// Log.d("XXX", "Product was erroniously purchased!"); - if(isLooping){ -// Log.d("XXX", "It is looping"); - error("Error while purchasing product"); - return; - } - isLooping=true; - PurchaseTask.this.purchase(sku, transactionId); - - } - - @Override - protected void error(String message) { - PurchaseTask.this.error(message); - - } - }.consume(sku); - return; - } - + PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT"); pc.setConsumableValue("validation_hash", sku, hash); diff --git a/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java b/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java new file mode 100644 index 0000000000..2f590a4e68 --- /dev/null +++ b/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java @@ -0,0 +1,87 @@ +package com.android.godot.payments; + +import java.util.ArrayList; + +import org.json.JSONException; +import org.json.JSONObject; + +import com.android.godot.Dictionary; +import com.android.godot.Godot; +import com.android.vending.billing.IInAppBillingService; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.RemoteException; +import android.util.Log; + +abstract public class ReleaseAllConsumablesTask { + + private Context context; + private IInAppBillingService mService; + + public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context ){ + this.context = context; + this.mService = mService; + } + + + public void consumeItAll(){ + try{ + Log.d("godot", "consumeItall for " + context.getPackageName()); + Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp",null); + + for (String key : bundle.keySet()) { + Object value = bundle.get(key); + Log.d("godot", String.format("%s %s (%s)", key, + value.toString(), value.getClass().getName())); + } + + + if (bundle.getInt("RESPONSE_CODE") == 0){ + + final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); + final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST"); + + + if (myPurchases == null || myPurchases.size() == 0){ + Log.d("godot", "No purchases!"); + notRequired(); + return; + } + + + Log.d("godot", "# products to be consumed:" + myPurchases.size()); + for (int i=0;i<myPurchases.size();i++) + { + + try{ + String receipt = myPurchases.get(i); + JSONObject inappPurchaseData = new JSONObject(receipt); + String sku = inappPurchaseData.getString("productId"); + String token = inappPurchaseData.getString("purchaseToken"); + String signature = mySignatures.get(i); + Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt); + new GenericConsumeTask(context, mService, sku, receipt,signature, token) { + + @Override + public void onSuccess(String sku, String receipt, String signature, String token) { + ReleaseAllConsumablesTask.this.success(sku, receipt, signature, token); + } + }.execute(); + + } catch (JSONException e) { + } + } + + } + }catch(Exception e){ + Log.d("godot", "Error releasing products:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + + abstract protected void success(String sku, String receipt, String signature, String token); + abstract protected void error(String message); + abstract protected void notRequired(); + +} |