diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3180e626..a2f7bf12 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -30,6 +30,10 @@
+
+
+
+
diff --git a/app/src/main/java/me/drakeet/support/toast/BadTokenListener.kt b/app/src/main/java/me/drakeet/support/toast/BadTokenListener.kt
deleted file mode 100644
index 78f5671a..00000000
--- a/app/src/main/java/me/drakeet/support/toast/BadTokenListener.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package me.drakeet.support.toast
-
-import android.widget.Toast
-
-/**
- * @author drakeet
- */
-fun interface BadTokenListener {
- fun onBadTokenCaught( toast : Toast)
-}
diff --git a/app/src/main/java/me/drakeet/support/toast/SafeToastContext.kt b/app/src/main/java/me/drakeet/support/toast/SafeToastContext.kt
deleted file mode 100644
index 5c91689e..00000000
--- a/app/src/main/java/me/drakeet/support/toast/SafeToastContext.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-package me.drakeet.support.toast
-
-import android.content.Context
-import android.content.ContextWrapper
-import android.util.Log
-import android.view.Display
-import android.view.View
-import android.view.ViewGroup
-import android.view.WindowManager
-import android.view.WindowManager.BadTokenException
-import android.widget.Toast
-
-/**
- * @author drakeet
- */
-internal class SafeToastContext(base : Context, private val toast : Toast) : ContextWrapper(base) {
-
- companion object {
- private const val TAG = "WindowManagerWrapper"
- }
-
- private var badTokenListener : BadTokenListener? = null
-
- fun setBadTokenListener(badTokenListener : BadTokenListener?) {
- this.badTokenListener = badTokenListener
- }
-
- override fun getApplicationContext() : Context =
- ApplicationContextWrapper(baseContext.applicationContext)
-
- inner class ApplicationContextWrapper(base : Context) : ContextWrapper(base) {
-
- override fun getSystemService(name : String) : Any? =
- if(WINDOW_SERVICE == name) {
- // noinspection ConstantConditions
- WindowManagerWrapper(baseContext.getSystemService(name) as WindowManager)
- } else{
- super.getSystemService(name)
- }
- }
-
- inner class WindowManagerWrapper(private val base : WindowManager) : WindowManager {
-
- @Suppress("DEPRECATION")
- override fun getDefaultDisplay() : Display? =
- base.defaultDisplay
-
- override fun removeViewImmediate(view : View) =
- base.removeViewImmediate(view)
-
- override fun updateViewLayout(view : View, params : ViewGroup.LayoutParams) =
- base.updateViewLayout(view, params)
-
- override fun removeView(view : View) =
- base.removeView(view)
-
- override fun addView(view : View, params : ViewGroup.LayoutParams) {
- try {
- Log.d(TAG, "WindowManager's addView(view, params) has been hooked.")
- base.addView(view, params)
- } catch(e : BadTokenException) {
- e.message?.let { Log.i(TAG, it) }
- badTokenListener?.onBadTokenCaught(toast)
- } catch(throwable : Throwable) {
- Log.e(TAG, "[addView]", throwable)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/me/drakeet/support/toast/ToastCompat.kt b/app/src/main/java/me/drakeet/support/toast/ToastCompat.kt
index 9dbf01d5..70556258 100644
--- a/app/src/main/java/me/drakeet/support/toast/ToastCompat.kt
+++ b/app/src/main/java/me/drakeet/support/toast/ToastCompat.kt
@@ -1,34 +1,122 @@
+// original implementation is https://github.com/PureWriter/ToastCompat
+/*
+ modification:
+ - convert from java to kotlin
+ - because Android 11's Toast.getView() returns null, we need to support view==null case.
+ - only in case of API 25 device, we have to create custom context and set it to view.
+*/
+
package me.drakeet.support.toast
import android.annotation.SuppressLint
import android.content.Context
+import android.content.ContextWrapper
import android.content.res.Resources
import android.os.Build
+import android.util.Log
+import android.view.Display
import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import android.view.WindowManager.BadTokenException
import android.widget.Toast
import androidx.annotation.StringRes
-// original implementation is https://github.com/PureWriter/ToastCompat
-// Android 11 でgetViewがnullを返すことが増えたので
-/**
- * @author drakeet
- */
-/**
- * Construct an empty Toast object. You must call [.setView] before you
- * can call [.show].
- *
- * @param context The context to use. Usually your [android.app.Application]
- * or [android.app.Activity] object.
- * @param baseToast The base toast
- */
+fun interface BadTokenListener {
+
+ fun onBadTokenCaught(toast : Toast)
+}
+
+internal class SafeToastContext(base : Context, private val toast : Toast) : ContextWrapper(base) {
+
+ companion object {
+
+ private const val TAG = "WindowManagerWrapper"
+ }
+
+ private var badTokenListener : BadTokenListener? = null
+
+ fun setBadTokenListener(badTokenListener : BadTokenListener?) {
+ this.badTokenListener = badTokenListener
+ }
+
+ override fun getApplicationContext() : Context =
+ ApplicationContextWrapper(baseContext.applicationContext)
+
+ inner class ApplicationContextWrapper(base : Context) : ContextWrapper(base) {
+
+ override fun getSystemService(name : String) : Any? =
+ if(WINDOW_SERVICE == name) {
+ // noinspection ConstantConditions
+ WindowManagerWrapper(baseContext.getSystemService(name) as WindowManager)
+ } else {
+ super.getSystemService(name)
+ }
+ }
+
+ inner class WindowManagerWrapper(private val base : WindowManager) : WindowManager {
+
+ @Suppress("DEPRECATION")
+ override fun getDefaultDisplay() : Display? =
+ base.defaultDisplay
+
+ override fun removeViewImmediate(view : View) =
+ base.removeViewImmediate(view)
+
+ override fun updateViewLayout(view : View, params : ViewGroup.LayoutParams) =
+ base.updateViewLayout(view, params)
+
+ override fun removeView(view : View) =
+ base.removeView(view)
+
+ override fun addView(view : View, params : ViewGroup.LayoutParams) {
+ try {
+ Log.d(TAG, "WindowManager's addView(view, params) has been hooked.")
+ base.addView(view, params)
+ } catch(e : BadTokenException) {
+ e.message?.let { Log.i(TAG, it) }
+ badTokenListener?.onBadTokenCaught(toast)
+ } catch(throwable : Throwable) {
+ Log.e(TAG, "[addView]", throwable)
+ }
+ }
+ }
+}
+
@Suppress("DEPRECATION")
-class ToastCompat(
+class ToastCompat private constructor(
context : Context,
- private val baseToast : Toast
+ private val original : Toast
) : Toast(context) {
companion object {
+ private fun setContextCompat(view : View?, contextCreator : () -> Context) {
+ if(view != null && Build.VERSION.SDK_INT == 25) {
+ try {
+ val field = View::class.java.getDeclaredField("mContext")
+ field.isAccessible = true
+ field[view] = contextCreator()
+ } catch(throwable : Throwable) {
+ throwable.printStackTrace()
+ }
+ }
+ }
+
+ /**
+ * Make a standard toast that just contains a text view with the text from a resource.
+ *
+ * @param context The context to use. Usually your [android.app.Application]
+ * or [android.app.Activity] object.
+ * @param resId The resource id of the string resource to use. Can be formatted text.
+ * @param duration How long to display the message. Either [.LENGTH_SHORT] or
+ * [.LENGTH_LONG]
+ * @throws Resources.NotFoundException if the resource can't be found.
+ */
+ @Suppress("unused")
+ fun makeText(context : Context, @StringRes resId : Int, duration : Int) =
+ makeText(context, context.resources.getText(resId), duration)
+
/**
* Make a standard toast that just contains a text view.
*
@@ -47,80 +135,56 @@ class ToastCompat(
return ToastCompat(context, toast)
}
- /**
- * Make a standard toast that just contains a text view with the text from a resource.
- *
- * @param context The context to use. Usually your [android.app.Application]
- * or [android.app.Activity] object.
- * @param resId The resource id of the string resource to use. Can be formatted text.
- * @param duration How long to display the message. Either [.LENGTH_SHORT] or
- * [.LENGTH_LONG]
- * @throws Resources.NotFoundException if the resource can't be found.
- */
- @Suppress("unused")
- fun makeText(context : Context, @StringRes resId : Int, duration : Int) : Toast {
- return makeText(context, context.resources.getText(resId), duration)
- }
-
- private fun setContextCompat(view : View?, contextCreator : () -> Context) {
- if(view != null && Build.VERSION.SDK_INT == 25) {
- try {
- val field = View::class.java.getDeclaredField("mContext")
- field.isAccessible = true
- field[view] = contextCreator()
- } catch(throwable : Throwable) {
- throwable.printStackTrace()
- }
- }
- }
}
fun setBadTokenListener(listener : BadTokenListener?) : ToastCompat {
- (baseToast.view?.context as? SafeToastContext)
+ (original.view?.context as? SafeToastContext)
?.setBadTokenListener(listener)
return this
}
override fun setView(view : View) {
- baseToast.view = view
- setContextCompat(baseToast.view) { SafeToastContext(view.context, this) }
+ original.view = view
+ setContextCompat(original.view) { SafeToastContext(view.context, original) }
}
- override fun getView() : View? = baseToast.view
+ override fun getView() : View? =
+ original.view
- override fun show() = baseToast.show()
+ override fun show() =
+ original.show()
override fun setDuration(duration : Int) {
- baseToast.duration = duration
+ original.duration = duration
}
override fun setGravity(gravity : Int, xOffset : Int, yOffset : Int) =
- baseToast.setGravity(gravity, xOffset, yOffset)
+ original.setGravity(gravity, xOffset, yOffset)
override fun setMargin(horizontalMargin : Float, verticalMargin : Float) =
- baseToast.setMargin(horizontalMargin, verticalMargin)
+ original.setMargin(horizontalMargin, verticalMargin)
override fun setText(resId : Int) =
- baseToast.setText(resId)
+ original.setText(resId)
override fun setText(s : CharSequence) =
- baseToast.setText(s)
+ original.setText(s)
- override fun getHorizontalMargin() : Float =
- baseToast.horizontalMargin
+ override fun getHorizontalMargin() =
+ original.horizontalMargin
- override fun getVerticalMargin() : Float =
- baseToast.verticalMargin
+ override fun getVerticalMargin() =
+ original.verticalMargin
- override fun getDuration() : Int =
- baseToast.duration
+ override fun getDuration() =
+ original.duration
- override fun getGravity() : Int =
- baseToast.gravity
+ override fun getGravity() =
+ original.gravity
- override fun getXOffset() : Int =
- baseToast.xOffset
+ override fun getXOffset() =
+ original.xOffset
- override fun getYOffset() : Int =
- baseToast.yOffset
-}
\ No newline at end of file
+ override fun getYOffset() =
+ original.yOffset
+}