Preload browser and page to speed up Custom Tabs

This commit is contained in:
Matte23
2021-01-20 12:37:32 +01:00
parent 5550de5836
commit bc2f0a93db
6 changed files with 128 additions and 7 deletions

View File

@@ -5,6 +5,12 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"

View File

@@ -19,6 +19,7 @@
package net.underdesk.circolapp
import android.app.DownloadManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -30,6 +31,9 @@ import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.SearchView
import androidx.browser.customtabs.CustomTabsClient
import androidx.browser.customtabs.CustomTabsServiceConnection
import androidx.browser.customtabs.CustomTabsSession
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
@@ -43,6 +47,7 @@ import kotlinx.coroutines.launch
import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AndroidDatabase
import net.underdesk.circolapp.databinding.ActivityMainBinding
import net.underdesk.circolapp.utils.CustomTabsHelper
import net.underdesk.circolapp.utils.DownloadableFile
import net.underdesk.circolapp.works.PollWork
@@ -58,6 +63,8 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
var refreshCallback: RefreshCallback? = null
override var fileToDownload: DownloadableFile? = null
var customTabsSession: CustomTabsSession? = null
override fun onCreate(savedInstanceState: Bundle?) {
loadDarkTheme()
super.onCreate(savedInstanceState)
@@ -88,6 +95,26 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
}
}
override fun onStart() {
val connection: CustomTabsServiceConnection = object : CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(
name: ComponentName,
client: CustomTabsClient
) {
client.warmup(0)
customTabsSession = client.newSession(null)
}
override fun onServiceDisconnected(name: ComponentName) {}
}
CustomTabsClient.bindCustomTabsService(
this,
CustomTabsHelper.getPreferredCustomTabsPackage(this),
connection
)
super.onStart()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)

View File

@@ -24,6 +24,7 @@ import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.databinding.ItemAttachmentBinding
import net.underdesk.circolapp.utils.DownloadableFile
import net.underdesk.circolapp.utils.FileUtils
@@ -31,9 +32,10 @@ import net.underdesk.circolapp.utils.FileUtils
class AttachmentAdapter(
private val attachmentsNames: List<String>,
private val attachmentsUrls: List<String>,
private val adapterCallback: CircularLetterAdapter.AdapterCallback
private val mainActivity: MainActivity,
) :
RecyclerView.Adapter<AttachmentAdapter.AttachmentViewHolder>() {
private val adapterCallback: CircularLetterAdapter.AdapterCallback = mainActivity
private lateinit var context: Context
inner class AttachmentViewHolder(binding: ItemAttachmentBinding) : RecyclerView.ViewHolder(binding.root) {
@@ -54,7 +56,7 @@ class AttachmentAdapter(
holder.title.text = attachmentsNames[position]
holder.viewButton.setOnClickListener {
FileUtils.viewFile(attachmentsUrls[position], context)
FileUtils.viewFile(attachmentsUrls[position], context, mainActivity.customTabsSession)
}
holder.shareButton.setOnClickListener {

View File

@@ -35,6 +35,7 @@ import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.underdesk.circolapp.AlarmBroadcastReceiver
import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AndroidDatabase
import net.underdesk.circolapp.databinding.ItemCircularBinding
@@ -45,11 +46,12 @@ import net.underdesk.circolapp.utils.FileUtils
class CircularLetterAdapter(
private var circulars: List<Circular>,
private val adapterCallback: AdapterCallback,
private val mainActivity: MainActivity,
private val adapterScope: CoroutineScope
) :
RecyclerView.Adapter<CircularLetterAdapter.CircularLetterViewHolder>() {
private lateinit var context: Context
private val adapterCallback: AdapterCallback = mainActivity
private var collapsedItems = -1
init {
@@ -136,6 +138,12 @@ class CircularLetterAdapter(
holder.attachmentsList.visibility = View.GONE
holder.attachmentsList.adapter = null
} else {
FileUtils.preloadFiles(
circulars[position].url,
circulars[position].attachmentsUrls,
mainActivity.customTabsSession
)
holder.collapseButton.setImageDrawable(
getDrawable(
context,
@@ -155,7 +163,7 @@ class CircularLetterAdapter(
holder.attachmentsList.adapter = AttachmentAdapter(
circulars[position].attachmentsNames,
circulars[position].attachmentsUrls,
adapterCallback
mainActivity
)
} else {
holder.attachmentsList.adapter = null
@@ -173,7 +181,7 @@ class CircularLetterAdapter(
}
}
FileUtils.viewFile(circulars[position].url, context)
FileUtils.viewFile(circulars[position].url, context, mainActivity.customTabsSession)
}
holder.shareButton.setOnClickListener {

View File

@@ -0,0 +1,57 @@
/*
* Circolapp
* Copyright (C) 2019-2020 Matteo Schiff
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.underdesk.circolapp.utils
import android.content.Context
import android.content.Intent
import android.content.pm.ResolveInfo
import android.net.Uri
object CustomTabsHelper {
private const val ACTION_CUSTOM_TABS_CONNECTION =
"android.support.customtabs.action.CustomTabsService"
fun getPreferredCustomTabsPackage(context: Context): String {
val packages = getCustomTabsPackages(context)
return if (packages.isEmpty()) "com.android.chrome" else packages[0].activityInfo.packageName
}
private fun getCustomTabsPackages(context: Context): ArrayList<ResolveInfo> {
val pm = context.packageManager
// Get default VIEW intent handler.
val activityIntent = Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.fromParts("http", "", null))
// Get all apps that can handle VIEW intents.
val resolvedActivityList = pm.queryIntentActivities(activityIntent, 0)
val packagesSupportingCustomTabs: ArrayList<ResolveInfo> = ArrayList()
for (info in resolvedActivityList) {
val serviceIntent = Intent()
serviceIntent.action = ACTION_CUSTOM_TABS_CONNECTION
serviceIntent.setPackage(info.activityInfo.packageName)
if (pm.resolveService(serviceIntent, 0) != null) {
packagesSupportingCustomTabs.add(info)
}
}
return packagesSupportingCustomTabs
}
}

View File

@@ -5,9 +5,12 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent.*
import androidx.browser.customtabs.CustomTabsService
import androidx.browser.customtabs.CustomTabsSession
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -16,7 +19,7 @@ import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter
object FileUtils {
fun viewFile(url: String, context: Context) {
fun viewFile(url: String, context: Context, session: CustomTabsSession?) {
if (url.endsWith(".pdf")) {
val viewIntent = Intent(Intent.ACTION_VIEW)
viewIntent.setDataAndType(Uri.parse(url), "application/pdf")
@@ -46,7 +49,7 @@ object FileUtils {
.setToolbarColor(primaryColor)
.build()
val customTabsIntent = Builder()
val customTabsIntent = Builder(session)
.setShowTitle(true)
.setColorScheme(COLOR_SCHEME_SYSTEM)
.setDefaultColorSchemeParams(otherParams)
@@ -57,6 +60,24 @@ object FileUtils {
}
}
fun preloadFiles(url: String, otherUrls: List<String>, session: CustomTabsSession?) {
if (!url.endsWith(".pdf")) {
val bundles = arrayListOf<Bundle>()
for (otherUrl in otherUrls) {
if (!url.endsWith(".pdf")) {
val bundle = Bundle().apply {
putParcelable(CustomTabsService.KEY_URL, Uri.parse(otherUrl))
}
bundles.add(bundle)
}
}
session?.mayLaunchUrl(Uri.parse(url), null, bundles)
}
}
fun shareFile(url: String, context: Context) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND