From 6a16e0449963759c447cb4b2269eec3fac822828 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Tue, 9 Jun 2020 18:27:32 +0530 Subject: [PATCH 01/11] Add initial PWA launch support --- app/src/main/AndroidManifest.xml | 7 +++ .../foundation/e/apps/PWA/PwaActivity.java | 56 ++++++++++++++++++ .../foundation/e/apps/PWA/PwaInstaller.kt | 10 ++-- .../e/apps/PWA/PwaWebViewClient.java | 59 +++++++++++++++++++ app/src/main/res/drawable/splash.xml | 10 ++++ app/src/main/res/layout/activity_pwa.xml | 6 ++ app/src/main/res/values/styles.xml | 9 +++ gradlew | 0 8 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/PWA/PwaActivity.java create mode 100644 app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java create mode 100644 app/src/main/res/drawable/splash.xml create mode 100644 app/src/main/res/layout/activity_pwa.xml mode change 100644 => 100755 gradlew diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1a6718172..552b723ad 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -66,6 +66,13 @@ android:label="XAPK Installer" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" /> + + + + + + \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java b/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java new file mode 100644 index 000000000..0efd86b49 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java @@ -0,0 +1,56 @@ +package foundation.e.apps.PWA; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import foundation.e.apps.R; + +public class PwaActivity extends AppCompatActivity { + + public static final String KEY_PWA_NAME = "PWA_NAME"; + public static final String KEY_SCOPE = "pwa_scope"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + if (intent == null) { + Toast.makeText(this, "URL can't be empty", Toast.LENGTH_SHORT).show(); + finish(); + } + + setDisplay(this); + //setOrientation(this); + setName(this); + setContentView(R.layout.activity_pwa); + setWebView((WebView)findViewById(R.id.webView)); + } + + private void setDisplay(Activity activity) { + //activity.setTheme(R.style.FullscreenTheme); + } + + private void setName(Activity activity) { + String name = getIntent().getStringExtra(KEY_PWA_NAME); + if (!name.isEmpty()) { + activity.setTitle(name); + } + } + + @SuppressLint("SetJavaScriptEnabled") + private void setWebView(WebView myWebView) { + WebSettings webSettings = myWebView.getSettings(); + webSettings.setJavaScriptEnabled(true); + String start_url = getIntent().getData().toString(); + String scope = getIntent().getStringExtra(KEY_SCOPE); + myWebView.setWebViewClient(new PwaWebViewClient(start_url, scope)); + myWebView.loadUrl(start_url); + } +} diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt b/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt index 79832c49d..8bbff69f5 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt +++ b/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt @@ -25,6 +25,7 @@ import java.io.FileNotFoundException import java.net.URL import java.util.* import javax.net.ssl.HttpsURLConnection +import android.content.ComponentName class PwaInstaller : AppCompatActivity() { @@ -79,15 +80,14 @@ class PwaInstaller : AppCompatActivity() { } val intent = Intent() intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) - intent.setAction(Intent.ACTION_VIEW) - intent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString()) + //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + intent.setAction("foundation.e.blisslauncher.VIEW_PWA") + intent.setComponent(ComponentName("foundation.e.apps", "foundation.e.apps.PWA.PwaActivity")) intent.setData(myUrl) + intent.putExtra("PWA_NAME", name) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) - - if (isExistShortcutInfo(name)) { Toast.makeText(this, "Shortcut already exist", Toast.LENGTH_SHORT).show() } else { diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java b/app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java new file mode 100644 index 000000000..6affe1af0 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java @@ -0,0 +1,59 @@ +package foundation.e.apps.PWA; + +import android.content.Intent; +import android.net.Uri; +import android.webkit.*; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.regex.Pattern; + +class PwaWebViewClient extends WebViewClient { + private Pattern scope_pattern; + + public PwaWebViewClient(String start_url, String scope) { + try { + URL baseUrl = new URL(start_url); + URL scopeUrl = new URL(baseUrl, scope); + if (!scopeUrl.toString().endsWith("*")) { + scopeUrl = new URL(scopeUrl, "*"); + } + + this.scope_pattern = this.regexFromPattern(scopeUrl.toString()); + } catch (MalformedURLException e) { + this.scope_pattern = null; + } + } + + @SuppressWarnings("deprecation") + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + if (this.scoped(url)) { + return false; + } else { + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + view.getContext().startActivity(i); + return true; + } + } + + private boolean scoped(String url) { + return this.scope_pattern == null || this.scope_pattern.matcher(url).matches(); + } + + private Pattern regexFromPattern(String pattern) { + final String toReplace = "\\.[]{}()^$?+|"; + StringBuilder regex = new StringBuilder(); + for (int i = 0; i < pattern.length(); i++) { + char c = pattern.charAt(i); + if (c == '*') { + regex.append("."); + } else if (toReplace.indexOf(c) > -1) { + regex.append('\\'); + } + regex.append(c); + } + return Pattern.compile(regex.toString()); + } +} + diff --git a/app/src/main/res/drawable/splash.xml b/app/src/main/res/drawable/splash.xml new file mode 100644 index 000000000..f39bb0a08 --- /dev/null +++ b/app/src/main/res/drawable/splash.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_pwa.xml b/app/src/main/res/layout/activity_pwa.xml new file mode 100644 index 000000000..9a6062e40 --- /dev/null +++ b/app/src/main/res/layout/activity_pwa.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b27fea813..831f3db83 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -60,5 +60,14 @@ 18sp @android:color/white + + + diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 -- GitLab From 1c8634a1cc665cac99bcfd644aa81e3fc5161412 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Tue, 9 Jun 2020 18:40:11 +0530 Subject: [PATCH 02/11] Use FLAG_ACTIVITY_NEW_DOCUMENT to open PWAs in different tasks --- app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt b/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt index 8bbff69f5..4e6e90938 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt +++ b/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt @@ -80,7 +80,7 @@ class PwaInstaller : AppCompatActivity() { } val intent = Intent() intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) intent.setAction("foundation.e.blisslauncher.VIEW_PWA") intent.setComponent(ComponentName("foundation.e.apps", "foundation.e.apps.PWA.PwaActivity")) intent.setData(myUrl) -- GitLab From 11f507f991eb22867a7837965b7ce165c8742841 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sat, 13 Jun 2020 12:22:43 +0530 Subject: [PATCH 03/11] Add permissions for PWA --- app/src/main/AndroidManifest.xml | 23 ++++-- .../foundation/e/apps/PWA/PwaActivity.java | 43 ++++++---- .../foundation/e/apps/PWA/PwaInstaller.kt | 6 +- .../e/apps/PWA/PwaWebChromeClient.kt | 81 +++++++++++++++++++ .../foundation/e/apps/api/HomePwaRequest.kt | 2 + app/src/main/res/values/strings.xml | 2 + 6 files changed, 134 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 552b723ad..3ebdb3756 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,22 +10,32 @@ android:name="android.permission.INSTALL_PACKAGES" tools:ignore="ProtectedPermissions" /> - - + + + + + + + + + + + + - + @@ -67,8 +77,7 @@ android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" /> - + diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java b/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java index 0efd86b49..96896ac15 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java +++ b/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java @@ -3,12 +3,15 @@ package foundation.e.apps.PWA; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; +import android.content.pm.PackageManager; import android.os.Bundle; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; + import foundation.e.apps.R; public class PwaActivity extends AppCompatActivity { @@ -16,6 +19,8 @@ public class PwaActivity extends AppCompatActivity { public static final String KEY_PWA_NAME = "PWA_NAME"; public static final String KEY_SCOPE = "pwa_scope"; + private PwaWebChromeClient pwaWebChromeClient; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -25,32 +30,42 @@ public class PwaActivity extends AppCompatActivity { Toast.makeText(this, "URL can't be empty", Toast.LENGTH_SHORT).show(); finish(); } - - setDisplay(this); - //setOrientation(this); - setName(this); + String name = getIntent().getStringExtra(KEY_PWA_NAME); + setName(this, name); setContentView(R.layout.activity_pwa); - setWebView((WebView)findViewById(R.id.webView)); - } - private void setDisplay(Activity activity) { - //activity.setTheme(R.style.FullscreenTheme); + pwaWebChromeClient = new PwaWebChromeClient(this, name); + setWebView((WebView) findViewById(R.id.webView), pwaWebChromeClient); + } - private void setName(Activity activity) { - String name = getIntent().getStringExtra(KEY_PWA_NAME); + private void setName(Activity activity, String name) { if (!name.isEmpty()) { activity.setTitle(name); } } @SuppressLint("SetJavaScriptEnabled") - private void setWebView(WebView myWebView) { - WebSettings webSettings = myWebView.getSettings(); + private void setWebView(WebView webView, PwaWebChromeClient pwaWebChromeClient) { + WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); String start_url = getIntent().getData().toString(); String scope = getIntent().getStringExtra(KEY_SCOPE); - myWebView.setWebViewClient(new PwaWebViewClient(start_url, scope)); - myWebView.loadUrl(start_url); + webView.setWebChromeClient(pwaWebChromeClient); + webView.setWebViewClient(new PwaWebViewClient(start_url, scope)); + webView.loadUrl(start_url); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + switch (requestCode) { + case PwaWebChromeClient.REQUEST_LOCATION_PERMISSION: { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + pwaWebChromeClient.locationPermissionGranted(); + } else { + pwaWebChromeClient.locationPermissionDenied(); + } + } + } } } diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt b/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt index 4e6e90938..201cc4be0 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt +++ b/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt @@ -26,6 +26,7 @@ import java.net.URL import java.util.* import javax.net.ssl.HttpsURLConnection import android.content.ComponentName +import android.util.Log class PwaInstaller : AppCompatActivity() { @@ -65,6 +66,7 @@ class PwaInstaller : AppCompatActivity() { Looper.prepare();//Call looper.prepare() try { var uri = PwasBasicData.thisActivity!!.uri + Log.d("PWA Installer", "installer: $uri") val url = URL(Constants.BASE_URL + "media/" + uri) val urlConnection = url.openConnection() as HttpsURLConnection urlConnection.requestMethod = Constants.REQUEST_METHOD_GET @@ -74,7 +76,7 @@ class PwaInstaller : AppCompatActivity() { scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) }catch (e: FileNotFoundException) { val x = R.drawable.pwa_default_icon - val icon = BitmapFactory.decodeResource(mActivity.getResources(), + icon = BitmapFactory.decodeResource(mActivity.getResources(), x) scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) } @@ -94,7 +96,7 @@ class PwaInstaller : AppCompatActivity() { Toast.makeText(this, "Shortcut created", Toast.LENGTH_SHORT).show() val shortcut = ShortcutInfo.Builder(mActivity, java.lang.Long.toString(Random().nextLong())) .setShortLabel(name.toString()) - .setIcon(Icon.createWithAdaptiveBitmap(scaledBitmap)) + .setIcon(Icon.createWithBitmap(icon)) .setIntent(intent) .build() @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt b/app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt new file mode 100644 index 000000000..72260e254 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt @@ -0,0 +1,81 @@ +package foundation.e.apps.PWA + +import android.Manifest +import android.content.Context +import android.content.DialogInterface +import android.content.pm.PackageManager +import android.net.Uri +import android.util.Log +import android.webkit.* +import android.widget.Toast +import androidx.appcompat.app.AlertDialog +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import foundation.e.apps.R + +class PwaWebChromeClient(private val pwaActivity: PwaActivity, private val pwaName: String) : WebChromeClient() { + + private lateinit var geoRequestOrigin: String + private var geoLocationCallback: GeolocationPermissions.Callback? = null + + override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) { + super.onGeolocationPermissionsShowPrompt(origin, callback) + if (ContextCompat.checkSelfPermission(pwaActivity, LOCATION_PERMISSION) + != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.shouldShowRequestPermissionRationale(pwaActivity, + Manifest.permission.ACCESS_FINE_LOCATION)) { + + AlertDialog.Builder(pwaActivity) + .setMessage(String.format(pwaActivity.resources.getString( + R.string.location_permission_rationale), pwaName)) + .setNegativeButton(android.R.string.cancel) { dialog, _ -> + dialog.dismiss() + } + .setPositiveButton(android.R.string.ok) { _, _ -> + geoRequestOrigin = origin + geoLocationCallback = callback + ActivityCompat.requestPermissions(pwaActivity, arrayOf(LOCATION_PERMISSION), + REQUEST_LOCATION_PERMISSION) + }.show() + } else { + geoRequestOrigin = origin + geoLocationCallback = callback + ActivityCompat.requestPermissions(pwaActivity, arrayOf(LOCATION_PERMISSION), + REQUEST_LOCATION_PERMISSION) + } + } else { + // Permission is already granted, Pass it to the callback. + callback.invoke(origin, true, true) + } + } + + fun locationPermissionGranted() { + geoLocationCallback?.invoke(geoRequestOrigin, true, true) + } + + fun locationPermissionDenied() { + geoLocationCallback?.invoke(geoRequestOrigin, false, false) + Toast.makeText(pwaActivity, R.string.permission_not_granted, Toast.LENGTH_SHORT).show() + } + + override fun onPermissionRequest(request: PermissionRequest?) { + Log.d(TAG, "onPermissionRequest() called with: request = $request") + super.onPermissionRequest(request) + } + + override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean { + Log.d(TAG, "onConsoleMessage() called with: consoleMessage = ${consoleMessage?.message()}") + return super.onConsoleMessage(consoleMessage) + } + + override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback>?, fileChooserParams: FileChooserParams?): Boolean { + Log.d(TAG, "onShowFileChooser() called with: webView = $webView, filePathCallback = $filePathCallback, fileChooserParams = $fileChooserParams") + return super.onShowFileChooser(webView, filePathCallback, fileChooserParams) + } + + companion object { + private const val TAG = "PwaWebChromeClient" + private const val LOCATION_PERMISSION = Manifest.permission.ACCESS_FINE_LOCATION + const val REQUEST_LOCATION_PERMISSION = 101 + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/api/HomePwaRequest.kt b/app/src/main/java/foundation/e/apps/api/HomePwaRequest.kt index 23998ff9d..feaba0cc8 100644 --- a/app/src/main/java/foundation/e/apps/api/HomePwaRequest.kt +++ b/app/src/main/java/foundation/e/apps/api/HomePwaRequest.kt @@ -1,6 +1,7 @@ package foundation.e.apps.api import android.content.Context +import android.util.Log import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty @@ -26,6 +27,7 @@ class HomePwaRequest { val url = Constants.BASE_URL + "apps?action=list_home&type=$appType" val urlConnection = Common.createConnection(url, Constants.REQUEST_METHOD_GET) val result = reader.readValue(urlConnection.inputStream) + Log.d("HomePwaRequest", "request: $result") urlConnection.disconnect() callback.invoke(null, result) } catch (e: Exception) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d64cfde01..f242b2bf8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -174,5 +174,7 @@ You are offline. Tap here to retry! PWA + %s needs to access location permission to show weather in your location. + Permission is not granted -- GitLab From 2d0e9580c955a3407f2e886cc9f7864c0a80d5d1 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sat, 13 Jun 2020 14:40:19 +0530 Subject: [PATCH 04/11] Following changes: 1. File Chooser is added to support file upload in webview. 2. Package name is changed from "PWA" to "pwa". 3. Automatically grant some permissions. --- app/src/main/AndroidManifest.xml | 5 +- .../e/apps/application/ApplicationActivity.kt | 2 +- .../e/apps/application/model/Application.kt | 2 +- .../e/apps/{PWA => pwa}/PwaActivity.java | 36 +++++++- .../e/apps/{PWA => pwa}/PwaInstaller.kt | 90 +++++++++---------- .../e/apps/{PWA => pwa}/PwaWebChromeClient.kt | 55 +++++++++--- .../e/apps/{PWA => pwa}/PwaWebViewClient.java | 5 +- .../res/layout/activity_pwa_installer.xml | 2 +- 8 files changed, 131 insertions(+), 66 deletions(-) rename app/src/main/java/foundation/e/apps/{PWA => pwa}/PwaActivity.java (62%) rename app/src/main/java/foundation/e/apps/{PWA => pwa}/PwaInstaller.kt (52%) rename app/src/main/java/foundation/e/apps/{PWA => pwa}/PwaWebChromeClient.kt (59%) rename app/src/main/java/foundation/e/apps/{PWA => pwa}/PwaWebViewClient.java (90%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3ebdb3756..21efbb36f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -68,7 +68,7 @@ android:name=".application.ScreenshotsActivity" android:theme="@style/FullScreenTheme" /> - + diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationActivity.kt b/app/src/main/java/foundation/e/apps/application/ApplicationActivity.kt index 2c51e6907..f860a001b 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationActivity.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationActivity.kt @@ -44,7 +44,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import com.google.android.material.snackbar.Snackbar import foundation.e.apps.MainActivity.Companion.sharedPreferences -import foundation.e.apps.PWA.PwaInstaller +import foundation.e.apps.pwa.PwaInstaller import foundation.e.apps.R import foundation.e.apps.application.model.Application import foundation.e.apps.application.model.ApplicationStateListener diff --git a/app/src/main/java/foundation/e/apps/application/model/Application.kt b/app/src/main/java/foundation/e/apps/application/model/Application.kt index a7665b29c..ce3e002d6 100644 --- a/app/src/main/java/foundation/e/apps/application/model/Application.kt +++ b/app/src/main/java/foundation/e/apps/application/model/Application.kt @@ -24,7 +24,7 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import foundation.e.apps.MainActivity.Companion.mActivity -import foundation.e.apps.PWA.PwaInstaller +import foundation.e.apps.pwa.PwaInstaller import foundation.e.apps.XAPK.XAPKFile import foundation.e.apps.api.AppDetailRequest import foundation.e.apps.api.AppDownloadedRequest diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java b/app/src/main/java/foundation/e/apps/pwa/PwaActivity.java similarity index 62% rename from app/src/main/java/foundation/e/apps/PWA/PwaActivity.java rename to app/src/main/java/foundation/e/apps/pwa/PwaActivity.java index 96896ac15..8512ba8c3 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaActivity.java +++ b/app/src/main/java/foundation/e/apps/pwa/PwaActivity.java @@ -1,15 +1,17 @@ -package foundation.e.apps.PWA; +package foundation.e.apps.pwa; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; +import android.view.KeyEvent; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import foundation.e.apps.R; @@ -20,6 +22,9 @@ public class PwaActivity extends AppCompatActivity { public static final String KEY_SCOPE = "pwa_scope"; private PwaWebChromeClient pwaWebChromeClient; + private WebView webView; + + private static final String TAG = "PwaActivity"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -35,7 +40,8 @@ public class PwaActivity extends AppCompatActivity { setContentView(R.layout.activity_pwa); pwaWebChromeClient = new PwaWebChromeClient(this, name); - setWebView((WebView) findViewById(R.id.webView), pwaWebChromeClient); + webView = (WebView) findViewById(R.id.webView); + setWebView(webView, pwaWebChromeClient); } @@ -49,8 +55,16 @@ public class PwaActivity extends AppCompatActivity { private void setWebView(WebView webView, PwaWebChromeClient pwaWebChromeClient) { WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); + webSettings.setAllowContentAccess(true); + webSettings.setLoadWithOverviewMode(true); + webSettings.setAllowFileAccess(true); + webSettings.setAllowUniversalAccessFromFileURLs(true); + webSettings.setAllowContentAccess(true); + webSettings.setAllowFileAccessFromFileURLs(true); + webSettings.setDomStorageEnabled(true); String start_url = getIntent().getData().toString(); String scope = getIntent().getStringExtra(KEY_SCOPE); + if(scope == null) scope = ""; webView.setWebChromeClient(pwaWebChromeClient); webView.setWebViewClient(new PwaWebViewClient(start_url, scope)); webView.loadUrl(start_url); @@ -68,4 +82,22 @@ public class PwaActivity extends AppCompatActivity { } } } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && webView != null && webView.canGoBack()) { + webView.goBack(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (requestCode == PwaWebChromeClient.REQUEST_FILE_CHOOSER) { + pwaWebChromeClient.onActivityResult(resultCode, data); + } + super.onActivityResult(requestCode, resultCode, data); + + } } diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt b/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt similarity index 52% rename from app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt rename to app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt index 201cc4be0..949881c86 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaInstaller.kt +++ b/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt @@ -1,6 +1,7 @@ -package foundation.e.apps.PWA +package foundation.e.apps.pwa import android.annotation.SuppressLint +import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.SharedPreferences @@ -13,7 +14,6 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Looper -import android.provider.Browser import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import foundation.e.apps.MainActivity.Companion.mActivity @@ -25,26 +25,23 @@ import java.io.FileNotFoundException import java.net.URL import java.util.* import javax.net.ssl.HttpsURLConnection -import android.content.ComponentName -import android.util.Log class PwaInstaller : AppCompatActivity() { - var icon : Bitmap?=null + var icon: Bitmap? = null private val sharedPrefFile = "kotlinsharedpreference" - var scaledBitmap :Bitmap?=null + var scaledBitmap: Bitmap? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_application) - sharedPreferences= this.getSharedPreferences(sharedPrefFile,Context.MODE_PRIVATE) - + sharedPreferences = this.getSharedPreferences(sharedPrefFile, Context.MODE_PRIVATE) val extras = intent.extras val name = extras.getString("NAME") - val Url = Uri.parse(extras.getString("URL")) - installer(name,Url) + val url = Uri.parse(extras.getString("URL")) + installer(name, url) } override fun onResume() { @@ -52,21 +49,20 @@ class PwaInstaller : AppCompatActivity() { finish() } - fun setBooleanConfig(key:String?,flag:Boolean){ - val editor:SharedPreferences.Editor = sharedPreferences!!.edit() - editor.putBoolean(key,flag) + private fun setBooleanConfig(key: String?, flag: Boolean) { + val editor: SharedPreferences.Editor = sharedPreferences!!.edit() + editor.putBoolean(key, flag) editor.apply() } private fun installer(name: String?, myUrl: Uri) { - setBooleanConfig(name,true) - Thread{ + setBooleanConfig(name, true) + Thread { run { - Looper.prepare();//Call looper.prepare() + Looper.prepare();//Call looper.prepare() try { var uri = PwasBasicData.thisActivity!!.uri - Log.d("PWA Installer", "installer: $uri") val url = URL(Constants.BASE_URL + "media/" + uri) val urlConnection = url.openConnection() as HttpsURLConnection urlConnection.requestMethod = Constants.REQUEST_METHOD_GET @@ -74,43 +70,43 @@ class PwaInstaller : AppCompatActivity() { urlConnection.readTimeout = Constants.READ_TIMEOUT icon = BitmapFactory.decodeStream(urlConnection.inputStream) scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) - }catch (e: FileNotFoundException) { + } catch (e: FileNotFoundException) { val x = R.drawable.pwa_default_icon icon = BitmapFactory.decodeResource(mActivity.getResources(), x) scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) } - val intent = Intent() - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) - intent.setAction("foundation.e.blisslauncher.VIEW_PWA") - intent.setComponent(ComponentName("foundation.e.apps", "foundation.e.apps.PWA.PwaActivity")) - intent.setData(myUrl) - intent.putExtra("PWA_NAME", name) - - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { - val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) - if (isExistShortcutInfo(name)) { - Toast.makeText(this, "Shortcut already exist", Toast.LENGTH_SHORT).show() - } else { - Toast.makeText(this, "Shortcut created", Toast.LENGTH_SHORT).show() - val shortcut = ShortcutInfo.Builder(mActivity, java.lang.Long.toString(Random().nextLong())) - .setShortLabel(name.toString()) - .setIcon(Icon.createWithBitmap(icon)) - .setIntent(intent) - .build() - @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - shortcutManager.requestPinShortcut(shortcut, null) - } + val intent = Intent() + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) + intent.action = "foundation.e.blisslauncher.VIEW_PWA" + intent.component = ComponentName(packageName, PwaActivity::class.java.canonicalName!!) + intent.data = myUrl + intent.putExtra("PWA_NAME", name) + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { + val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) + if (isExistShortcutInfo(name)) { + Toast.makeText(this, "Shortcut already exist", Toast.LENGTH_SHORT).show() } else { - val installer = Intent() - installer.putExtra("android.intent.extra.shortcut.INTENT", intent) - installer.putExtra("android.intent.extra.shortcut.NAME", name) - installer.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap) - installer.putExtra("duplicate", false); - installer.setAction("com.android.launcher.action.INSTALL_SHORTCUT") - mActivity.sendBroadcast(installer) + Toast.makeText(this, "Shortcut created", Toast.LENGTH_SHORT).show() + val shortcut = ShortcutInfo.Builder(mActivity, java.lang.Long.toString(Random().nextLong())) + .setShortLabel(name.toString()) + .setIcon(Icon.createWithBitmap(icon)) + .setIntent(intent) + .build() + @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") + shortcutManager.requestPinShortcut(shortcut, null) } + } else { + val installer = Intent() + installer.putExtra("android.intent.extra.shortcut.INTENT", intent) + installer.putExtra("android.intent.extra.shortcut.NAME", name) + installer.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap) + installer.putExtra("duplicate", false); + installer.setAction("com.android.launcher.action.INSTALL_SHORTCUT") + mActivity.sendBroadcast(installer) + } Looper.loop(); } }.start() diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt b/app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt similarity index 59% rename from app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt rename to app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt index 72260e254..c81bcc5c1 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaWebChromeClient.kt +++ b/app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt @@ -1,8 +1,8 @@ -package foundation.e.apps.PWA +package foundation.e.apps.pwa import android.Manifest -import android.content.Context -import android.content.DialogInterface +import android.content.ActivityNotFoundException +import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.util.Log @@ -17,6 +17,7 @@ class PwaWebChromeClient(private val pwaActivity: PwaActivity, private val pwaNa private lateinit var geoRequestOrigin: String private var geoLocationCallback: GeolocationPermissions.Callback? = null + private var filePathCallback: ValueCallback>? = null override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) { super.onGeolocationPermissionsShowPrompt(origin, callback) @@ -59,23 +60,55 @@ class PwaWebChromeClient(private val pwaActivity: PwaActivity, private val pwaNa } override fun onPermissionRequest(request: PermissionRequest?) { - Log.d(TAG, "onPermissionRequest() called with: request = $request") - super.onPermissionRequest(request) + request?.grant(request.resources) } - override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean { - Log.d(TAG, "onConsoleMessage() called with: consoleMessage = ${consoleMessage?.message()}") - return super.onConsoleMessage(consoleMessage) + override fun onShowFileChooser(webView: WebView?, + filePathCallback: ValueCallback>?, + fileChooserParams: FileChooserParams?): Boolean { + openFileInput(filePathCallback, fileChooserParams) + return true } - override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback>?, fileChooserParams: FileChooserParams?): Boolean { - Log.d(TAG, "onShowFileChooser() called with: webView = $webView, filePathCallback = $filePathCallback, fileChooserParams = $fileChooserParams") - return super.onShowFileChooser(webView, filePathCallback, fileChooserParams) + private fun openFileInput(callback: ValueCallback>?, + fileChooserParams: FileChooserParams?) { + val allowMultiple = fileChooserParams?.mode == FileChooserParams.MODE_OPEN_MULTIPLE + if (filePathCallback != null) { + filePathCallback!!.onReceiveValue(null) + } + + filePathCallback = callback + var intent = fileChooserParams?.createIntent() + + // Create intent if fileChooserParams Intent is null. + if (intent == null) { + intent = Intent(Intent.ACTION_GET_CONTENT) + intent.addCategory(Intent.CATEGORY_OPENABLE) + intent.type = "*/*" + } + + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultiple) + try { + pwaActivity.startActivityForResult(Intent.createChooser(intent, "Open with"), REQUEST_FILE_CHOOSER) + } catch (e: ActivityNotFoundException) { + e.printStackTrace() + Toast.makeText(pwaActivity, "Activity can't be resolved", Toast.LENGTH_SHORT).show() + } + } + + // Called whenever a file chooser event is completed + fun onActivityResult(resultCode: Int, data: Intent?) { + if (filePathCallback != null) { + val result = FileChooserParams.parseResult(resultCode, data) + filePathCallback!!.onReceiveValue(result) + filePathCallback = null // Clear the callback. + } } companion object { private const val TAG = "PwaWebChromeClient" private const val LOCATION_PERMISSION = Manifest.permission.ACCESS_FINE_LOCATION const val REQUEST_LOCATION_PERMISSION = 101 + const val REQUEST_FILE_CHOOSER = 102 } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java b/app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java similarity index 90% rename from app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java rename to app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java index 6affe1af0..357101dcd 100644 --- a/app/src/main/java/foundation/e/apps/PWA/PwaWebViewClient.java +++ b/app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java @@ -1,4 +1,4 @@ -package foundation.e.apps.PWA; +package foundation.e.apps.pwa; import android.content.Intent; import android.net.Uri; @@ -11,6 +11,8 @@ import java.util.regex.Pattern; class PwaWebViewClient extends WebViewClient { private Pattern scope_pattern; + private static final String TAG = "PwaWebViewClient"; + public PwaWebViewClient(String start_url, String scope) { try { URL baseUrl = new URL(start_url); @@ -21,6 +23,7 @@ class PwaWebViewClient extends WebViewClient { this.scope_pattern = this.regexFromPattern(scopeUrl.toString()); } catch (MalformedURLException e) { + e.printStackTrace(); this.scope_pattern = null; } } diff --git a/app/src/main/res/layout/activity_pwa_installer.xml b/app/src/main/res/layout/activity_pwa_installer.xml index 5d0bee8ca..77f84efed 100644 --- a/app/src/main/res/layout/activity_pwa_installer.xml +++ b/app/src/main/res/layout/activity_pwa_installer.xml @@ -3,6 +3,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".PWA.PwaInstaller"> + tools:context=".pwa.PwaInstaller"> \ No newline at end of file -- GitLab From b99435db51f6ba259461e778eac68320e8a19753 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Wed, 24 Jun 2020 15:25:42 +0530 Subject: [PATCH 05/11] Remove unnecessary code that is migrated into separate PWA player --- app/src/main/AndroidManifest.xml | 18 +-- .../foundation/e/apps/pwa/PwaActivity.java | 103 ---------------- .../foundation/e/apps/pwa/PwaDummyActivity.kt | 21 ++++ .../foundation/e/apps/pwa/PwaInstaller.kt | 88 +++++++++----- .../e/apps/pwa/PwaWebChromeClient.kt | 114 ------------------ .../e/apps/pwa/PwaWebViewClient.java | 62 ---------- app/src/main/res/values/strings.xml | 2 +- app/src/main/res/values/styles.xml | 3 +- 8 files changed, 84 insertions(+), 327 deletions(-) delete mode 100644 app/src/main/java/foundation/e/apps/pwa/PwaActivity.java create mode 100644 app/src/main/java/foundation/e/apps/pwa/PwaDummyActivity.kt delete mode 100644 app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt delete mode 100644 app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 21efbb36f..286563055 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,12 +19,7 @@ - - - - - - + - + @@ -76,13 +71,10 @@ android:label="XAPK Installer" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" /> + - - - - - \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/pwa/PwaActivity.java b/app/src/main/java/foundation/e/apps/pwa/PwaActivity.java deleted file mode 100644 index 8512ba8c3..000000000 --- a/app/src/main/java/foundation/e/apps/pwa/PwaActivity.java +++ /dev/null @@ -1,103 +0,0 @@ -package foundation.e.apps.pwa; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.view.KeyEvent; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; - -import foundation.e.apps.R; - -public class PwaActivity extends AppCompatActivity { - - public static final String KEY_PWA_NAME = "PWA_NAME"; - public static final String KEY_SCOPE = "pwa_scope"; - - private PwaWebChromeClient pwaWebChromeClient; - private WebView webView; - - private static final String TAG = "PwaActivity"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Intent intent = getIntent(); - if (intent == null) { - Toast.makeText(this, "URL can't be empty", Toast.LENGTH_SHORT).show(); - finish(); - } - String name = getIntent().getStringExtra(KEY_PWA_NAME); - setName(this, name); - setContentView(R.layout.activity_pwa); - - pwaWebChromeClient = new PwaWebChromeClient(this, name); - webView = (WebView) findViewById(R.id.webView); - setWebView(webView, pwaWebChromeClient); - - } - - private void setName(Activity activity, String name) { - if (!name.isEmpty()) { - activity.setTitle(name); - } - } - - @SuppressLint("SetJavaScriptEnabled") - private void setWebView(WebView webView, PwaWebChromeClient pwaWebChromeClient) { - WebSettings webSettings = webView.getSettings(); - webSettings.setJavaScriptEnabled(true); - webSettings.setAllowContentAccess(true); - webSettings.setLoadWithOverviewMode(true); - webSettings.setAllowFileAccess(true); - webSettings.setAllowUniversalAccessFromFileURLs(true); - webSettings.setAllowContentAccess(true); - webSettings.setAllowFileAccessFromFileURLs(true); - webSettings.setDomStorageEnabled(true); - String start_url = getIntent().getData().toString(); - String scope = getIntent().getStringExtra(KEY_SCOPE); - if(scope == null) scope = ""; - webView.setWebChromeClient(pwaWebChromeClient); - webView.setWebViewClient(new PwaWebViewClient(start_url, scope)); - webView.loadUrl(start_url); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - switch (requestCode) { - case PwaWebChromeClient.REQUEST_LOCATION_PERMISSION: { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - pwaWebChromeClient.locationPermissionGranted(); - } else { - pwaWebChromeClient.locationPermissionDenied(); - } - } - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK && webView != null && webView.canGoBack()) { - webView.goBack(); - return true; - } - return super.onKeyDown(keyCode, event); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - if (requestCode == PwaWebChromeClient.REQUEST_FILE_CHOOSER) { - pwaWebChromeClient.onActivityResult(resultCode, data); - } - super.onActivityResult(requestCode, resultCode, data); - - } -} diff --git a/app/src/main/java/foundation/e/apps/pwa/PwaDummyActivity.kt b/app/src/main/java/foundation/e/apps/pwa/PwaDummyActivity.kt new file mode 100644 index 000000000..1ec300243 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/pwa/PwaDummyActivity.kt @@ -0,0 +1,21 @@ +package foundation.e.apps.pwa + +import android.content.ComponentName +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity + +class PwaDummyActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val intent = intent + if (intent == null) { + Toast.makeText(this, "URL can't be empty", Toast.LENGTH_SHORT).show() + finish() + } else { + intent.component = ComponentName("foundation.e.pwaplayer", "foundation.e.pwaplayer.player.PwaActivity") + startActivity(intent) + finish() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt b/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt index 949881c86..cea4449b7 100644 --- a/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt +++ b/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt @@ -1,10 +1,7 @@ package foundation.e.apps.pwa import android.annotation.SuppressLint -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.SharedPreferences +import android.content.* import android.content.pm.ShortcutInfo import android.content.pm.ShortcutManager import android.graphics.Bitmap @@ -14,6 +11,7 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Looper +import android.util.Log import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import foundation.e.apps.MainActivity.Companion.mActivity @@ -23,9 +21,10 @@ import foundation.e.apps.application.model.data.PwasBasicData import foundation.e.apps.utils.Constants import java.io.FileNotFoundException import java.net.URL -import java.util.* import javax.net.ssl.HttpsURLConnection +private const val TAG = "PwaInstaller" + class PwaInstaller : AppCompatActivity() { var icon: Bitmap? = null @@ -39,9 +38,14 @@ class PwaInstaller : AppCompatActivity() { sharedPreferences = this.getSharedPreferences(sharedPrefFile, Context.MODE_PRIVATE) val extras = intent.extras - val name = extras.getString("NAME") - val url = Uri.parse(extras.getString("URL")) - installer(name, url) + val name = extras?.getString("NAME") + val url = Uri.parse(extras?.getString("URL")) + if (name == null || url == null) { + Log.d(TAG, "Name or Url must not be null") + finish() + } else { + installer(name, url) + } } override fun onResume() { @@ -49,82 +53,100 @@ class PwaInstaller : AppCompatActivity() { finish() } - private fun setBooleanConfig(key: String?, flag: Boolean) { + private fun setBooleanConfig(key: String) { val editor: SharedPreferences.Editor = sharedPreferences!!.edit() - editor.putBoolean(key, flag) + editor.putBoolean(key, true) editor.apply() } - private fun installer(name: String?, myUrl: Uri) { - setBooleanConfig(name, true) + private fun installer(name: String, pwaUrl: Uri) { + //TODO: Add in content provider first and then make a shortcut + setBooleanConfig(name) + val contentResolver = contentResolver Thread { run { - Looper.prepare();//Call looper.prepare() + Looper.prepare() //Call looper.prepare() try { - var uri = PwasBasicData.thisActivity!!.uri + val uri = PwasBasicData.thisActivity!!.uri val url = URL(Constants.BASE_URL + "media/" + uri) val urlConnection = url.openConnection() as HttpsURLConnection urlConnection.requestMethod = Constants.REQUEST_METHOD_GET urlConnection.connectTimeout = Constants.CONNECT_TIMEOUT urlConnection.readTimeout = Constants.READ_TIMEOUT icon = BitmapFactory.decodeStream(urlConnection.inputStream) - scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) + //scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) } catch (e: FileNotFoundException) { val x = R.drawable.pwa_default_icon icon = BitmapFactory.decodeResource(mActivity.getResources(), x) - scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) + //scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true) } - val intent = Intent() + val intent = Intent(this, PwaDummyActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) intent.action = "foundation.e.blisslauncher.VIEW_PWA" - intent.component = ComponentName(packageName, PwaActivity::class.java.canonicalName!!) - intent.data = myUrl + intent.data = pwaUrl intent.putExtra("PWA_NAME", name) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) - if (isExistShortcutInfo(name)) { + if (isExistShortcutInfo(pwaUrl.toString())) { Toast.makeText(this, "Shortcut already exist", Toast.LENGTH_SHORT).show() } else { + val values = ContentValues() + val id = pwaUrl.toString() + writeToValues(id, name, pwaUrl, values) + val uri = contentResolver.insert(Uri.parse("content://foundation.e.pwaplayer.provider/pwa"), values) + if (uri == null) { + Toast.makeText(this, "Can't install the pwa", Toast.LENGTH_SHORT).show() + return@Thread + } Toast.makeText(this, "Shortcut created", Toast.LENGTH_SHORT).show() - val shortcut = ShortcutInfo.Builder(mActivity, java.lang.Long.toString(Random().nextLong())) - .setShortLabel(name.toString()) + val shortcut = ShortcutInfo.Builder(mActivity, pwaUrl.toString()) + .setShortLabel(name) .setIcon(Icon.createWithBitmap(icon)) .setIntent(intent) .build() - @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") shortcutManager.requestPinShortcut(shortcut, null) } } else { + val values = ContentValues() + val id = pwaUrl.toString() + writeToValues(id, name, pwaUrl, values) + val uri = contentResolver.insert(Uri.parse("content://foundation.e.pwaplayer.provider/pwa"), values) + if (uri == null) { + Toast.makeText(this, "Can't install the pwa", Toast.LENGTH_SHORT).show() + return@Thread + } val installer = Intent() installer.putExtra("android.intent.extra.shortcut.INTENT", intent) installer.putExtra("android.intent.extra.shortcut.NAME", name) installer.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap) - installer.putExtra("duplicate", false); - installer.setAction("com.android.launcher.action.INSTALL_SHORTCUT") + installer.putExtra("duplicate", false) + installer.action = "com.android.launcher.action.INSTALL_SHORTCUT" mActivity.sendBroadcast(installer) } - Looper.loop(); + Looper.loop() } }.start() } + private fun writeToValues(id: String, name: String, pwaUrl: Uri, values: ContentValues) { + values.put("URL", pwaUrl.toString()) + values.put("SHORTCUT_ID", id) + values.put("NAME", name) + } + companion object { @SuppressLint("NewApi") - fun isExistShortcutInfo(shortcutId: String?): Boolean { + fun isExistShortcutInfo(shortcutId: String): Boolean { val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) - - val shortcutInfoList = shortcutManager!!.getPinnedShortcuts() + val shortcutInfoList = shortcutManager.pinnedShortcuts for (info in shortcutInfoList) { - if (info.getId() == shortcutId) { - - } - if (info.getShortLabel() == shortcutId) { + if (info.id == shortcutId) { return true } } diff --git a/app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt b/app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt deleted file mode 100644 index c81bcc5c1..000000000 --- a/app/src/main/java/foundation/e/apps/pwa/PwaWebChromeClient.kt +++ /dev/null @@ -1,114 +0,0 @@ -package foundation.e.apps.pwa - -import android.Manifest -import android.content.ActivityNotFoundException -import android.content.Intent -import android.content.pm.PackageManager -import android.net.Uri -import android.util.Log -import android.webkit.* -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import foundation.e.apps.R - -class PwaWebChromeClient(private val pwaActivity: PwaActivity, private val pwaName: String) : WebChromeClient() { - - private lateinit var geoRequestOrigin: String - private var geoLocationCallback: GeolocationPermissions.Callback? = null - private var filePathCallback: ValueCallback>? = null - - override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) { - super.onGeolocationPermissionsShowPrompt(origin, callback) - if (ContextCompat.checkSelfPermission(pwaActivity, LOCATION_PERMISSION) - != PackageManager.PERMISSION_GRANTED) { - if (ActivityCompat.shouldShowRequestPermissionRationale(pwaActivity, - Manifest.permission.ACCESS_FINE_LOCATION)) { - - AlertDialog.Builder(pwaActivity) - .setMessage(String.format(pwaActivity.resources.getString( - R.string.location_permission_rationale), pwaName)) - .setNegativeButton(android.R.string.cancel) { dialog, _ -> - dialog.dismiss() - } - .setPositiveButton(android.R.string.ok) { _, _ -> - geoRequestOrigin = origin - geoLocationCallback = callback - ActivityCompat.requestPermissions(pwaActivity, arrayOf(LOCATION_PERMISSION), - REQUEST_LOCATION_PERMISSION) - }.show() - } else { - geoRequestOrigin = origin - geoLocationCallback = callback - ActivityCompat.requestPermissions(pwaActivity, arrayOf(LOCATION_PERMISSION), - REQUEST_LOCATION_PERMISSION) - } - } else { - // Permission is already granted, Pass it to the callback. - callback.invoke(origin, true, true) - } - } - - fun locationPermissionGranted() { - geoLocationCallback?.invoke(geoRequestOrigin, true, true) - } - - fun locationPermissionDenied() { - geoLocationCallback?.invoke(geoRequestOrigin, false, false) - Toast.makeText(pwaActivity, R.string.permission_not_granted, Toast.LENGTH_SHORT).show() - } - - override fun onPermissionRequest(request: PermissionRequest?) { - request?.grant(request.resources) - } - - override fun onShowFileChooser(webView: WebView?, - filePathCallback: ValueCallback>?, - fileChooserParams: FileChooserParams?): Boolean { - openFileInput(filePathCallback, fileChooserParams) - return true - } - - private fun openFileInput(callback: ValueCallback>?, - fileChooserParams: FileChooserParams?) { - val allowMultiple = fileChooserParams?.mode == FileChooserParams.MODE_OPEN_MULTIPLE - if (filePathCallback != null) { - filePathCallback!!.onReceiveValue(null) - } - - filePathCallback = callback - var intent = fileChooserParams?.createIntent() - - // Create intent if fileChooserParams Intent is null. - if (intent == null) { - intent = Intent(Intent.ACTION_GET_CONTENT) - intent.addCategory(Intent.CATEGORY_OPENABLE) - intent.type = "*/*" - } - - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultiple) - try { - pwaActivity.startActivityForResult(Intent.createChooser(intent, "Open with"), REQUEST_FILE_CHOOSER) - } catch (e: ActivityNotFoundException) { - e.printStackTrace() - Toast.makeText(pwaActivity, "Activity can't be resolved", Toast.LENGTH_SHORT).show() - } - } - - // Called whenever a file chooser event is completed - fun onActivityResult(resultCode: Int, data: Intent?) { - if (filePathCallback != null) { - val result = FileChooserParams.parseResult(resultCode, data) - filePathCallback!!.onReceiveValue(result) - filePathCallback = null // Clear the callback. - } - } - - companion object { - private const val TAG = "PwaWebChromeClient" - private const val LOCATION_PERMISSION = Manifest.permission.ACCESS_FINE_LOCATION - const val REQUEST_LOCATION_PERMISSION = 101 - const val REQUEST_FILE_CHOOSER = 102 - } -} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java b/app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java deleted file mode 100644 index 357101dcd..000000000 --- a/app/src/main/java/foundation/e/apps/pwa/PwaWebViewClient.java +++ /dev/null @@ -1,62 +0,0 @@ -package foundation.e.apps.pwa; - -import android.content.Intent; -import android.net.Uri; -import android.webkit.*; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.regex.Pattern; - -class PwaWebViewClient extends WebViewClient { - private Pattern scope_pattern; - - private static final String TAG = "PwaWebViewClient"; - - public PwaWebViewClient(String start_url, String scope) { - try { - URL baseUrl = new URL(start_url); - URL scopeUrl = new URL(baseUrl, scope); - if (!scopeUrl.toString().endsWith("*")) { - scopeUrl = new URL(scopeUrl, "*"); - } - - this.scope_pattern = this.regexFromPattern(scopeUrl.toString()); - } catch (MalformedURLException e) { - e.printStackTrace(); - this.scope_pattern = null; - } - } - - @SuppressWarnings("deprecation") - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (this.scoped(url)) { - return false; - } else { - Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - view.getContext().startActivity(i); - return true; - } - } - - private boolean scoped(String url) { - return this.scope_pattern == null || this.scope_pattern.matcher(url).matches(); - } - - private Pattern regexFromPattern(String pattern) { - final String toReplace = "\\.[]{}()^$?+|"; - StringBuilder regex = new StringBuilder(); - for (int i = 0; i < pattern.length(); i++) { - char c = pattern.charAt(i); - if (c == '*') { - regex.append("."); - } else if (toReplace.indexOf(c) > -1) { - regex.append('\\'); - } - regex.append(c); - } - return Pattern.compile(regex.toString()); - } -} - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f242b2bf8..ee1b4f30b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -170,7 +170,7 @@ No error. This app is incompatible with your device. - //pwa + You are offline. Tap here to retry! PWA diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 831f3db83..b44cef5df 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -60,7 +60,8 @@ 18sp @android:color/white -