From 041a22599224dae84349f3be64259267750e9bb9 Mon Sep 17 00:00:00 2001 From: Amine Date: Sat, 3 Jun 2017 22:52:01 +0200 Subject: [PATCH] Updated Custom tab code and added buttons at the bottom of the article viewer. --- .../bou/readerforselfoss/ReaderActivity.kt | 23 +++- .../customtabs/CustomTabActivityHelper.java | 101 +++++++++--------- .../utils/customtabs/ServiceConnection.java | 32 ++++++ .../customtabs/ServiceConnectionCallback.java | 18 ++++ app/src/main/res/layout/activity_reader.xml | 61 ++++++++++- app/src/main/res/layout/list_item.xml | 53 +++++---- build.gradle | 2 +- 7 files changed, 212 insertions(+), 78 deletions(-) create mode 100644 app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnection.java create mode 100644 app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnectionCallback.java diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/ReaderActivity.kt b/app/src/main/java/apps/amine/bou/readerforselfoss/ReaderActivity.kt index a078ee2..57b3fa3 100644 --- a/app/src/main/java/apps/amine/bou/readerforselfoss/ReaderActivity.kt +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/ReaderActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageButton import android.widget.ImageView import android.widget.TextView import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi @@ -44,6 +45,9 @@ class ReaderActivity : DragDismissActivity() { val content = v.findViewById(R.id.content) as HtmlTextView val url = intent.getStringExtra("url") val parser = MercuryApi(getString(R.string.mercury)) + val browserBtn: ImageButton = v.findViewById(R.id.browserBtn) as ImageButton + val shareBtn: ImageButton = v.findViewById(R.id.shareBtn) as ImageButton + val customTabsIntent = buildCustomTabsIntent(this@ReaderActivity) mCustomTabActivityHelper = CustomTabActivityHelper() @@ -52,13 +56,30 @@ class ReaderActivity : DragDismissActivity() { parser.parseUrl(url).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { - if (response.body() != null) { + if (response.body() != null && response.body()!!.content.isNotEmpty()) { source.text = response.body()!!.domain title.text = response.body()!!.title if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true)) if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty()) Glide.with(applicationContext).load(response.body()!!.lead_image_url).asBitmap().fitCenter().into(image) + + shareBtn.setOnClickListener { + val sendIntent = Intent() + sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + sendIntent.action = Intent.ACTION_SEND + sendIntent.putExtra(Intent.EXTRA_TEXT, response.body()!!.url) + sendIntent.type = "text/plain" + startActivity(Intent.createChooser(sendIntent, getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) + } + + browserBtn.setOnClickListener { + val intent = Intent(Intent.ACTION_VIEW) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + intent.data = Uri.parse(response.body()!!.url) + startActivity(intent) + } + hideProgressBar() } else { errorAfterMercuryCall() diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/CustomTabActivityHelper.java b/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/CustomTabActivityHelper.java index 8c287df..461cae3 100644 --- a/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/CustomTabActivityHelper.java +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/CustomTabActivityHelper.java @@ -1,7 +1,6 @@ package apps.amine.bou.readerforselfoss.utils.customtabs; import android.app.Activity; -import android.content.ComponentName; import android.net.Uri; import android.os.Bundle; import android.support.customtabs.CustomTabsClient; @@ -11,28 +10,30 @@ import android.support.customtabs.CustomTabsSession; import java.util.List; -@SuppressWarnings("ALL") -public class CustomTabActivityHelper { +/** + * This is a helper class to manage the connection to the Custom Tabs Service. + */ +public class CustomTabActivityHelper implements ServiceConnectionCallback { private CustomTabsSession mCustomTabsSession; private CustomTabsClient mClient; private CustomTabsServiceConnection mConnection; private ConnectionCallback mConnectionCallback; /** - * Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView + * Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView. * - * @param activity The host activity - * @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available - * @param uri the Uri to be opened - * @param fallback a CustomTabFallback to be used if Custom Tabs is not available + * @param activity The host activity. + * @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available. + * @param uri the Uri to be opened. + * @param fallback a CustomTabFallback to be used if Custom Tabs is not available. */ public static void openCustomTab(Activity activity, - CustomTabsIntent customTabsIntent, - Uri uri, - CustomTabFallback fallback) { + CustomTabsIntent customTabsIntent, + Uri uri, + CustomTabFallback fallback) { String packageName = CustomTabsHelper.getPackageNameToUse(activity); - //If we cant find a package name, it means there's no browser that supports + //If we cant find a package name, it means theres no browser that supports //Chrome Custom Tabs installed. So, we fallback to the webview if (packageName == null) { if (fallback != null) { @@ -45,22 +46,21 @@ public class CustomTabActivityHelper { } /** - * Unbinds the Activity from the Custom Tabs Service - * @param activity the activity that is connected to the service + * Unbinds the Activity from the Custom Tabs Service. + * @param activity the activity that is connected to the service. */ public void unbindCustomTabsService(Activity activity) { - try { - if (mConnection == null) return; - activity.unbindService(mConnection); - mClient = null; - mCustomTabsSession = null; - } catch (RuntimeException e) {} + if (mConnection == null) return; + activity.unbindService(mConnection); + mClient = null; + mCustomTabsSession = null; + mConnection = null; } /** - * Creates or retrieves an exiting CustomTabsSession + * Creates or retrieves an exiting CustomTabsSession. * - * @return a CustomTabsSession + * @return a CustomTabsSession. */ public CustomTabsSession getSession() { if (mClient == null) { @@ -72,7 +72,7 @@ public class CustomTabActivityHelper { } /** - * Register a Callback to be called when connected or disconnected from the Custom Tabs Service + * Register a Callback to be called when connected or disconnected from the Custom Tabs Service. * @param connectionCallback */ public void setConnectionCallback(ConnectionCallback connectionCallback) { @@ -80,67 +80,72 @@ public class CustomTabActivityHelper { } /** - * Binds the Activity to the Custom Tabs Service - * @param activity the activity to be binded to the service + * Binds the Activity to the Custom Tabs Service. + * @param activity the activity to be binded to the service. */ public void bindCustomTabsService(Activity activity) { if (mClient != null) return; String packageName = CustomTabsHelper.getPackageNameToUse(activity); if (packageName == null) return; - mConnection = new CustomTabsServiceConnection() { - @Override - public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { - mClient = client; - mClient.warmup(0L); - if (mConnectionCallback != null) mConnectionCallback.onCustomTabsConnected(); - //Initialize a session as soon as possible. - getSession(); - } - @Override - public void onServiceDisconnected(ComponentName name) { - mClient = null; - if (mConnectionCallback != null) mConnectionCallback.onCustomTabsDisconnected(); - } - }; + mConnection = new ServiceConnection(this); CustomTabsClient.bindCustomTabsService(activity, packageName, mConnection); } + /** + * @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}. + * @return true if call to mayLaunchUrl was accepted. + */ public boolean mayLaunchUrl(Uri uri, Bundle extras, List otherLikelyBundles) { if (mClient == null) return false; CustomTabsSession session = getSession(); - return session != null && session.mayLaunchUrl(uri, extras, otherLikelyBundles); + if (session == null) return false; + return session.mayLaunchUrl(uri, extras, otherLikelyBundles); + } + + @Override + public void onServiceConnected(CustomTabsClient client) { + mClient = client; + mClient.warmup(0L); + if (mConnectionCallback != null) mConnectionCallback.onCustomTabsConnected(); + } + + @Override + public void onServiceDisconnected() { + mClient = null; + mCustomTabsSession = null; + if (mConnectionCallback != null) mConnectionCallback.onCustomTabsDisconnected(); } /** * A Callback for when the service is connected or disconnected. Use those callbacks to - * handle UI changes when the service is connected or disconnected + * handle UI changes when the service is connected or disconnected. */ public interface ConnectionCallback { /** - * Called when the service is connected + * Called when the service is connected. */ void onCustomTabsConnected(); /** - * Called when the service is disconnected + * Called when the service is disconnected. */ void onCustomTabsDisconnected(); } /** - * To be used as a fallback to open the Uri when Custom Tabs is not available + * To be used as a fallback to open the Uri when Custom Tabs is not available. */ public interface CustomTabFallback { /** * - * @param activity The Activity that wants to open the Uri - * @param uri The uri to be opened by the fallback + * @param activity The Activity that wants to open the Uri. + * @param uri The uri to be opened by the fallback. */ void openUri(Activity activity, Uri uri); } -} +} \ No newline at end of file diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnection.java b/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnection.java new file mode 100644 index 0000000..02685e6 --- /dev/null +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnection.java @@ -0,0 +1,32 @@ +package apps.amine.bou.readerforselfoss.utils.customtabs; + +import android.content.ComponentName; +import android.support.customtabs.CustomTabsClient; +import android.support.customtabs.CustomTabsServiceConnection; + +import java.lang.ref.WeakReference; + +/** + * Implementation for the CustomTabsServiceConnection that avoids leaking the + * ServiceConnectionCallback + */ +public class ServiceConnection extends CustomTabsServiceConnection { + // A weak reference to the ServiceConnectionCallback to avoid leaking it. + private WeakReference mConnectionCallback; + + public ServiceConnection(ServiceConnectionCallback connectionCallback) { + mConnectionCallback = new WeakReference<>(connectionCallback); + } + + @Override + public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { + ServiceConnectionCallback connectionCallback = mConnectionCallback.get(); + if (connectionCallback != null) connectionCallback.onServiceConnected(client); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + ServiceConnectionCallback connectionCallback = mConnectionCallback.get(); + if (connectionCallback != null) connectionCallback.onServiceDisconnected(); + } +} \ No newline at end of file diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnectionCallback.java b/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnectionCallback.java new file mode 100644 index 0000000..5f470a9 --- /dev/null +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/utils/customtabs/ServiceConnectionCallback.java @@ -0,0 +1,18 @@ +package apps.amine.bou.readerforselfoss.utils.customtabs; + + +import android.support.customtabs.CustomTabsClient; + + +public interface ServiceConnectionCallback { + /** + * Called when the service is connected. + * @param client a CustomTabsClient + */ + void onServiceConnected(CustomTabsClient client); + + /** + * Called when the service is disconnected. + */ + void onServiceDisconnected(); +} diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index e75a3ab..26dc236 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -62,5 +62,64 @@ app:layout_constraintHorizontal_bias="0.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toBottomOf="@+id/title" /> + app:layout_constraintTop_toBottomOf="@+id/title" + tools:text="Some text @android:string/fingerprint_icon_content_description" /> + + + + + + + + + diff --git a/app/src/main/res/layout/list_item.xml b/app/src/main/res/layout/list_item.xml index b2f1b3d..686dfc1 100644 --- a/app/src/main/res/layout/list_item.xml +++ b/app/src/main/res/layout/list_item.xml @@ -54,65 +54,64 @@ android:gravity="start" /> - + app:layout_constraintTop_toBottomOf="@+id/sourceTitleAndDate"> + app:icon_size="22dp" + app:icon_type="heart" /> + android:src="@drawable/ic_share_black_24dp" + android:tint="#000000" /> + android:src="@drawable/ic_open_in_browser_black_24dp" + android:tint="#000000" /> diff --git a/build.gradle b/build.gradle index 64b4c75..e62c4d7 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0-alpha2' + classpath 'com.android.tools.build:gradle:3.0.0-alpha3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong