From 20b8fee0fc6bd45fba5d47043b2e77c7e08604cb Mon Sep 17 00:00:00 2001 From: Sergey Eremin Date: Wed, 18 Jan 2017 14:21:40 +0300 Subject: [PATCH] Issue #8 paid apps support --- app/build.gradle | 2 +- .../yeriomin/yalpstore/DetailsActivity.java | 57 +++++++++++++++++-- .../yalpstore/NotPurchasedException.java | 4 ++ .../yalpstore/PlayStoreApiWrapper.java | 43 ++++++++++---- app/src/main/res/values-ru/strings.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- 6 files changed, 94 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/com/github/yeriomin/yalpstore/NotPurchasedException.java diff --git a/app/build.gradle b/app/build.gradle index a2f27de17..b31d337de 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,5 +24,5 @@ android { } dependencies { - compile 'com.github.yeriomin:play-store-api:0.3' + compile 'com.github.yeriomin:play-store-api:cfd47603fa' } diff --git a/app/src/main/java/com/github/yeriomin/yalpstore/DetailsActivity.java b/app/src/main/java/com/github/yeriomin/yalpstore/DetailsActivity.java index 670a1394f..abea8dc1a 100644 --- a/app/src/main/java/com/github/yeriomin/yalpstore/DetailsActivity.java +++ b/app/src/main/java/com/github/yeriomin/yalpstore/DetailsActivity.java @@ -3,9 +3,12 @@ package com.github.yeriomin.yalpstore; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; +import android.app.DownloadManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -52,6 +55,23 @@ public class DetailsActivity extends Activity { private List reviews = new ArrayList<>(); private Menu menu; private App app; + private long downloadId; + private BroadcastReceiver receiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + Bundle extras = intent.getExtras(); + if (null != extras) { + long id = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID); + System.out.println("downloadId=" + downloadId + " id=" + id); + if (downloadId == id) { + Button button = (Button) findViewById(R.id.download); + button.setText(R.string.details_install); + button.setEnabled(true); + } + } + } + }; @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -158,6 +178,20 @@ public class DetailsActivity extends Activity { task.execute(); } + @Override + protected void onPause() { + unregisterReceiver(receiver); + super.onPause(); + } + + @Override + protected void onResume() { + IntentFilter filter = new IntentFilter(); + filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE); + registerReceiver(receiver, filter); + super.onResume(); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -282,13 +316,14 @@ public class DetailsActivity extends Activity { setText(R.id.permissions, TextUtils.join("\n", localizedPermissions)); Button downloadButton = (Button) findViewById(R.id.download); - if (!app.isFree()) { - downloadButton.setText(getString(R.string.details_download_nonfree)); - downloadButton.setEnabled(false); - } else if (app.getVersionCode() == 0) { + if (app.getVersionCode() == 0) { downloadButton.setText(getString(R.string.details_download_impossible)); downloadButton.setEnabled(false); } else { + final boolean exists = PlayStoreApiWrapper.getApkPath(app).exists(); + if (exists) { + downloadButton.setText(R.string.details_install); + } downloadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -297,12 +332,24 @@ public class DetailsActivity extends Activity { protected Throwable doInBackground(Void... params) { PlayStoreApiWrapper wrapper = new PlayStoreApiWrapper(DetailsActivity.this); try { - wrapper.download(app); + downloadId = wrapper.download(app); } catch (Throwable e) { return e; } return null; } + + @Override + protected void onPostExecute(Throwable e) { + super.onPostExecute(e); + if (null == e && !exists) { + Button button = (Button) findViewById(R.id.download); + button.setText(R.string.details_downloading); + button.setEnabled(false); + } else if (e instanceof NotPurchasedException) { + Toast.makeText(getApplicationContext(), getString(R.string.error_not_purchased), Toast.LENGTH_LONG).show(); + } + } }; task.setContext(v.getContext()); task.prepareDialog( diff --git a/app/src/main/java/com/github/yeriomin/yalpstore/NotPurchasedException.java b/app/src/main/java/com/github/yeriomin/yalpstore/NotPurchasedException.java new file mode 100644 index 000000000..b999fb4be --- /dev/null +++ b/app/src/main/java/com/github/yeriomin/yalpstore/NotPurchasedException.java @@ -0,0 +1,4 @@ +package com.github.yeriomin.yalpstore; + +public class NotPurchasedException extends Exception { +} diff --git a/app/src/main/java/com/github/yeriomin/yalpstore/PlayStoreApiWrapper.java b/app/src/main/java/com/github/yeriomin/yalpstore/PlayStoreApiWrapper.java index 75d5af962..e38d036c3 100644 --- a/app/src/main/java/com/github/yeriomin/yalpstore/PlayStoreApiWrapper.java +++ b/app/src/main/java/com/github/yeriomin/yalpstore/PlayStoreApiWrapper.java @@ -14,6 +14,7 @@ import com.github.yeriomin.playstoreapi.AndroidAppDeliveryData; import com.github.yeriomin.playstoreapi.AppDetails; import com.github.yeriomin.playstoreapi.BulkDetailsEntry; import com.github.yeriomin.playstoreapi.BuyResponse; +import com.github.yeriomin.playstoreapi.DeliveryResponse; import com.github.yeriomin.playstoreapi.DocV2; import com.github.yeriomin.playstoreapi.GooglePlayAPI; import com.github.yeriomin.playstoreapi.HttpCookie; @@ -250,30 +251,48 @@ public class PlayStoreApiWrapper { return suggestions; } - public void download(App app) throws IOException { - File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); - String filename = app.getPackageName() + "." + String.valueOf(app.getVersionCode()) + ".apk"; - File fullPath = new File(downloadsDir, filename); + public long download(App app) throws IOException, NotPurchasedException { + File path = getApkPath(app); - if (fullPath.exists()) { - Log.i(this.getClass().getName(), filename + " exists. No download needed."); - context.startActivity(getOpenApkIntent(context, fullPath)); + if (path.exists()) { + Log.i(this.getClass().getName(), path.getName() + " exists. No download needed."); + context.startActivity(getOpenApkIntent(context, path)); } else { - Log.i(this.getClass().getName(), "Downloading apk to " + filename); - BuyResponse response = getApi().purchase(app.getPackageName(), app.getVersionCode(), app.getOfferType()); - AndroidAppDeliveryData appDeliveryData = response.getPurchaseStatusResponse().getAppDeliveryData(); + Log.i(this.getClass().getName(), "Downloading apk to " + path.getName()); + AndroidAppDeliveryData appDeliveryData; + if (app.isFree()) { + BuyResponse response = getApi().purchase(app.getPackageName(), app.getVersionCode(), app.getOfferType()); + appDeliveryData = response.getPurchaseStatusResponse().getAppDeliveryData(); + } else { + DeliveryResponse response = getApi().delivery(app.getPackageName(), app.getVersionCode(), app.getOfferType()); + if (response.hasAppDeliveryData()) { + appDeliveryData = response.getAppDeliveryData(); + } else { + throw new NotPurchasedException(); + } + } // Download manager cannot download https on old android versions String downloadUrl = appDeliveryData.getDownloadUrl().replace("https", "http"); HttpCookie downloadAuthCookie = appDeliveryData.getDownloadAuthCookie(0); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl)); request.addRequestHeader("Cookie", downloadAuthCookie.getName() + "=" + downloadAuthCookie.getValue()); - Uri uri = Uri.withAppendedPath(Uri.fromFile(downloadsDir), filename); + Uri uri = Uri.withAppendedPath( + Uri.fromFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)), + path.getName() + ); request.setDestinationUri(uri); request.setTitle(app.getDisplayName()); - ((DownloadManager) this.context.getSystemService(DOWNLOAD_SERVICE)).enqueue(request); + return ((DownloadManager) this.context.getSystemService(DOWNLOAD_SERVICE)).enqueue(request); } + return 0L; + } + + static public File getApkPath(App app) { + File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + String filename = app.getPackageName() + "." + String.valueOf(app.getVersionCode()) + ".apk"; + return new File(downloadsDir, filename); } static public Intent getOpenApkIntent(Context context, File file) { diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d4fd14e74..a73aa8774 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -27,6 +27,7 @@ Введите данные для доступа к аккаунту google Нет соединения с сетью. Сетевая ошибка: %s + Похоже, это приложение не было куплено. %s ↓ %.1f★ %d★ %d @@ -41,7 +42,8 @@ Версия %s Версия %s → %s Скачать - Платное приложение - скачать не получится + Установить + Скачиваем… Ошибка. Не удалось получить версию приложения млн млрд diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e873b0534..d39eb594d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,6 +27,7 @@ Provide google account credentials, please. No network connection. Network error: %s + The app does not seem to be purchased. %s ↓ %.1f★ %d★ %d @@ -41,7 +42,8 @@ Version %s Version %s → %s Download - App is not free - download disabled + Install + Downloading… Error. Could not get app version. mil bil