diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 006e99059ea1bbf4dca8c00fe97159a3ad902fd1..52792486bd659de9ed33bdffb53225e112a76f0d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,12 +10,14 @@ android:name="android.permission.INSTALL_PACKAGES" tools:ignore="ProtectedPermissions" /> - - + + + + 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.createWithAdaptiveBitmap(scaledBitmap)) - .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() - } - - companion object { - - @SuppressLint("NewApi") - fun isExistShortcutInfo(shortcutId: String?): Boolean { - val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) - - val shortcutInfoList = shortcutManager!!.getPinnedShortcuts() - - for (info in shortcutInfoList) { - if (info.getId() == shortcutId) { - - } - if (info.getShortLabel() == shortcutId) { - return true - } - } - return false - } - } -} 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 7e804bca6ded19911d3663f0377bcddc33ca87cb..af4cb22d04dd595cefb093ea0aa5a0c60a10a5a9 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.JsonIgnore 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 2c51e6907bd5f044c1f099a57118a3c45cf4f2dc..f860a001b767bb8aa703d9a9c9225c1f1bd352e6 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 a721b552b81c5b0bab96ad42788dba4b9033a589..131ca0c8457f4fba3b1f166dc7832de508d2cd2e 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/Extensions.kt b/app/src/main/java/foundation/e/apps/pwa/Extensions.kt new file mode 100644 index 0000000000000000000000000000000000000000..b38a5900b0a55467d4ddddc5390d839015c8cab6 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/pwa/Extensions.kt @@ -0,0 +1,24 @@ +package foundation.e.apps.pwa + +import android.R.attr.bitmap +import android.graphics.Bitmap +import android.util.Log +import java.io.ByteArrayOutputStream +import java.io.IOException + + +fun Bitmap.toByteArray(): ByteArray? { + // Try go guesstimate how much space the icon will take when serialized + // to avoid unnecessary allocations/copies during the write. + val size: Int = this.width * this.height * 4 + val out = ByteArrayOutputStream(size) + return try { + this.compress(Bitmap.CompressFormat.PNG, 100, out) + out.flush() + out.close() + out.toByteArray() + } catch (e: IOException) { + Log.w("Bitmap", "Could not write bitmap") + null + } +} \ 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 new file mode 100644 index 0000000000000000000000000000000000000000..19c90b9d8e96b4842dc4b63e91c7ab9a6618e9d6 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/pwa/PwaInstaller.kt @@ -0,0 +1,161 @@ +package foundation.e.apps.pwa + +import android.annotation.SuppressLint +import android.content.* +import android.content.pm.ShortcutInfo +import android.content.pm.ShortcutManager +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.drawable.Icon +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 +import foundation.e.apps.MainActivity.Companion.sharedPreferences +import foundation.e.apps.R +import foundation.e.apps.application.model.data.PwasBasicData +import foundation.e.apps.utils.Constants +import java.io.FileNotFoundException +import java.net.URL +import javax.net.ssl.HttpsURLConnection + +private const val TAG = "PwaInstaller" + +class PwaInstaller : AppCompatActivity() { + + lateinit var icon: Bitmap + private val sharedPrefFile = "kotlinsharedpreference" + var scaledBitmap: Bitmap? = null + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_application) + sharedPreferences = this.getSharedPreferences(sharedPrefFile, Context.MODE_PRIVATE) + + val extras = intent.extras + 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() { + super.onResume() + finish() + } + + private fun setBooleanConfig(key: String) { + val editor: SharedPreferences.Editor = sharedPreferences!!.edit() + editor.putBoolean(key, true) + editor.apply() + } + + + 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() + try { + 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) + } 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.action = "foundation.e.blisslauncher.VIEW_PWA" + 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(pwaUrl.toString())) { + Toast.makeText(this, "Shortcut already exist", Toast.LENGTH_SHORT).show() + } else { + val values = ContentValues() + val id = pwaUrl.toString() + writeToValues(id, name, pwaUrl, icon, 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 db_id = ContentUris.parseId(uri) + intent.putExtra("PWA_ID", db_id) + Toast.makeText(this, "Shortcut created", Toast.LENGTH_SHORT).show() + val shortcut = ShortcutInfo.Builder(mActivity, pwaUrl.toString()) + .setShortLabel(name) + .setIcon(Icon.createWithBitmap(icon)) + .setIntent(intent) + .build() + shortcutManager.requestPinShortcut(shortcut, null) + } + } else { + val values = ContentValues() + val id = pwaUrl.toString() + writeToValues(id, name, pwaUrl, icon, 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 db_id = ContentUris.parseId(uri) + intent.putExtra("PWA_ID", db_id) + 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.action = "com.android.launcher.action.INSTALL_SHORTCUT" + mActivity.sendBroadcast(installer) + } + Looper.loop() + } + }.start() + } + + private fun writeToValues(id: String, name: String, pwaUrl: Uri, icon: Bitmap, outValues: ContentValues) { + outValues.put("URL", pwaUrl.toString()) + outValues.put("SHORTCUT_ID", id) + outValues.put("TITLE", name) + outValues.put("ICON", icon.toByteArray()) + } + + companion object { + + @SuppressLint("NewApi") + fun isExistShortcutInfo(shortcutId: String): Boolean { + val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java) + val shortcutInfoList = shortcutManager.pinnedShortcuts + + for (info in shortcutInfoList) { + if (info.id == shortcutId) { + return true + } + } + return false + } + } +} diff --git a/app/src/main/res/drawable/splash.xml b/app/src/main/res/drawable/splash.xml new file mode 100644 index 0000000000000000000000000000000000000000..f39bb0a08402204bbb31293e3d412b8a71c72205 --- /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 0000000000000000000000000000000000000000..9a6062e409c9308876cf701155753b74cf23bcf6 --- /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/layout/activity_pwa_installer.xml b/app/src/main/res/layout/activity_pwa_installer.xml index 5d0bee8ca40f222eba52f1b8feb87d4989c75c48..77f84efed530998cf59713670c7ab49256bf9707 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 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d64cfde01848ac22646d15ba8939046d8f0da325..e8a17b08a116fceeb062b33141c3591396a4b044 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 e387c6e7b99bd70f138e5994bec21b1ff9530505..177214e5c5080945db1b114637312cf275b63396 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -64,4 +64,14 @@ @android:color/white + + + + diff --git a/gradlew b/gradlew old mode 100644 new mode 100755