mirror of
https://github.com/Matte23/circolapp.git
synced 2025-12-06 07:29:10 +00:00
Preload browser and page to speed up Custom Tabs
This commit is contained in:
@@ -5,6 +5,12 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.support.customtabs.action.CustomTabsService" />
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package net.underdesk.circolapp
|
package net.underdesk.circolapp
|
||||||
|
|
||||||
import android.app.DownloadManager
|
import android.app.DownloadManager
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@@ -30,6 +31,9 @@ import android.view.MenuItem
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.widget.SearchView
|
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.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
import androidx.navigation.ui.AppBarConfiguration
|
||||||
@@ -43,6 +47,7 @@ import kotlinx.coroutines.launch
|
|||||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||||
import net.underdesk.circolapp.data.AndroidDatabase
|
import net.underdesk.circolapp.data.AndroidDatabase
|
||||||
import net.underdesk.circolapp.databinding.ActivityMainBinding
|
import net.underdesk.circolapp.databinding.ActivityMainBinding
|
||||||
|
import net.underdesk.circolapp.utils.CustomTabsHelper
|
||||||
import net.underdesk.circolapp.utils.DownloadableFile
|
import net.underdesk.circolapp.utils.DownloadableFile
|
||||||
import net.underdesk.circolapp.works.PollWork
|
import net.underdesk.circolapp.works.PollWork
|
||||||
|
|
||||||
@@ -58,6 +63,8 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
|
|||||||
var refreshCallback: RefreshCallback? = null
|
var refreshCallback: RefreshCallback? = null
|
||||||
override var fileToDownload: DownloadableFile? = null
|
override var fileToDownload: DownloadableFile? = null
|
||||||
|
|
||||||
|
var customTabsSession: CustomTabsSession? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
loadDarkTheme()
|
loadDarkTheme()
|
||||||
super.onCreate(savedInstanceState)
|
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 {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_main, menu)
|
menuInflater.inflate(R.menu.menu_main, menu)
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.view.ViewGroup
|
|||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import net.underdesk.circolapp.MainActivity
|
||||||
import net.underdesk.circolapp.databinding.ItemAttachmentBinding
|
import net.underdesk.circolapp.databinding.ItemAttachmentBinding
|
||||||
import net.underdesk.circolapp.utils.DownloadableFile
|
import net.underdesk.circolapp.utils.DownloadableFile
|
||||||
import net.underdesk.circolapp.utils.FileUtils
|
import net.underdesk.circolapp.utils.FileUtils
|
||||||
@@ -31,9 +32,10 @@ import net.underdesk.circolapp.utils.FileUtils
|
|||||||
class AttachmentAdapter(
|
class AttachmentAdapter(
|
||||||
private val attachmentsNames: List<String>,
|
private val attachmentsNames: List<String>,
|
||||||
private val attachmentsUrls: List<String>,
|
private val attachmentsUrls: List<String>,
|
||||||
private val adapterCallback: CircularLetterAdapter.AdapterCallback
|
private val mainActivity: MainActivity,
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<AttachmentAdapter.AttachmentViewHolder>() {
|
RecyclerView.Adapter<AttachmentAdapter.AttachmentViewHolder>() {
|
||||||
|
private val adapterCallback: CircularLetterAdapter.AdapterCallback = mainActivity
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
|
|
||||||
inner class AttachmentViewHolder(binding: ItemAttachmentBinding) : RecyclerView.ViewHolder(binding.root) {
|
inner class AttachmentViewHolder(binding: ItemAttachmentBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
@@ -54,7 +56,7 @@ class AttachmentAdapter(
|
|||||||
holder.title.text = attachmentsNames[position]
|
holder.title.text = attachmentsNames[position]
|
||||||
|
|
||||||
holder.viewButton.setOnClickListener {
|
holder.viewButton.setOnClickListener {
|
||||||
FileUtils.viewFile(attachmentsUrls[position], context)
|
FileUtils.viewFile(attachmentsUrls[position], context, mainActivity.customTabsSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.shareButton.setOnClickListener {
|
holder.shareButton.setOnClickListener {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.underdesk.circolapp.AlarmBroadcastReceiver
|
import net.underdesk.circolapp.AlarmBroadcastReceiver
|
||||||
|
import net.underdesk.circolapp.MainActivity
|
||||||
import net.underdesk.circolapp.R
|
import net.underdesk.circolapp.R
|
||||||
import net.underdesk.circolapp.data.AndroidDatabase
|
import net.underdesk.circolapp.data.AndroidDatabase
|
||||||
import net.underdesk.circolapp.databinding.ItemCircularBinding
|
import net.underdesk.circolapp.databinding.ItemCircularBinding
|
||||||
@@ -45,11 +46,12 @@ import net.underdesk.circolapp.utils.FileUtils
|
|||||||
|
|
||||||
class CircularLetterAdapter(
|
class CircularLetterAdapter(
|
||||||
private var circulars: List<Circular>,
|
private var circulars: List<Circular>,
|
||||||
private val adapterCallback: AdapterCallback,
|
private val mainActivity: MainActivity,
|
||||||
private val adapterScope: CoroutineScope
|
private val adapterScope: CoroutineScope
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<CircularLetterAdapter.CircularLetterViewHolder>() {
|
RecyclerView.Adapter<CircularLetterAdapter.CircularLetterViewHolder>() {
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
|
private val adapterCallback: AdapterCallback = mainActivity
|
||||||
private var collapsedItems = -1
|
private var collapsedItems = -1
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -136,6 +138,12 @@ class CircularLetterAdapter(
|
|||||||
holder.attachmentsList.visibility = View.GONE
|
holder.attachmentsList.visibility = View.GONE
|
||||||
holder.attachmentsList.adapter = null
|
holder.attachmentsList.adapter = null
|
||||||
} else {
|
} else {
|
||||||
|
FileUtils.preloadFiles(
|
||||||
|
circulars[position].url,
|
||||||
|
circulars[position].attachmentsUrls,
|
||||||
|
mainActivity.customTabsSession
|
||||||
|
)
|
||||||
|
|
||||||
holder.collapseButton.setImageDrawable(
|
holder.collapseButton.setImageDrawable(
|
||||||
getDrawable(
|
getDrawable(
|
||||||
context,
|
context,
|
||||||
@@ -155,7 +163,7 @@ class CircularLetterAdapter(
|
|||||||
holder.attachmentsList.adapter = AttachmentAdapter(
|
holder.attachmentsList.adapter = AttachmentAdapter(
|
||||||
circulars[position].attachmentsNames,
|
circulars[position].attachmentsNames,
|
||||||
circulars[position].attachmentsUrls,
|
circulars[position].attachmentsUrls,
|
||||||
adapterCallback
|
mainActivity
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
holder.attachmentsList.adapter = null
|
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 {
|
holder.shareButton.setOnClickListener {
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,12 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
||||||
import androidx.browser.customtabs.CustomTabsIntent.*
|
import androidx.browser.customtabs.CustomTabsIntent.*
|
||||||
|
import androidx.browser.customtabs.CustomTabsService
|
||||||
|
import androidx.browser.customtabs.CustomTabsSession
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
@@ -16,7 +19,7 @@ import net.underdesk.circolapp.R
|
|||||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||||
|
|
||||||
object FileUtils {
|
object FileUtils {
|
||||||
fun viewFile(url: String, context: Context) {
|
fun viewFile(url: String, context: Context, session: CustomTabsSession?) {
|
||||||
if (url.endsWith(".pdf")) {
|
if (url.endsWith(".pdf")) {
|
||||||
val viewIntent = Intent(Intent.ACTION_VIEW)
|
val viewIntent = Intent(Intent.ACTION_VIEW)
|
||||||
viewIntent.setDataAndType(Uri.parse(url), "application/pdf")
|
viewIntent.setDataAndType(Uri.parse(url), "application/pdf")
|
||||||
@@ -46,7 +49,7 @@ object FileUtils {
|
|||||||
.setToolbarColor(primaryColor)
|
.setToolbarColor(primaryColor)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val customTabsIntent = Builder()
|
val customTabsIntent = Builder(session)
|
||||||
.setShowTitle(true)
|
.setShowTitle(true)
|
||||||
.setColorScheme(COLOR_SCHEME_SYSTEM)
|
.setColorScheme(COLOR_SCHEME_SYSTEM)
|
||||||
.setDefaultColorSchemeParams(otherParams)
|
.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) {
|
fun shareFile(url: String, context: Context) {
|
||||||
val sendIntent: Intent = Intent().apply {
|
val sendIntent: Intent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
|
|||||||
Reference in New Issue
Block a user