setShortcutInfo in NotificationCompat.Builder and pushDynamicShortcut in ShortcutManagerCompat doesn't work in Api 30(Android 11) - android-11

I am working on Bubbles in Android 11 and some functions doesn't work
I don't know how to fix this.
Android Studio writes:
Unresolved reference: setShortcutInfo
My NotificationCompat.Builder:
val builder = NotificationCompat.Builder(
appContext,
CHANNEL_WHATEVER
)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Um, hi!")
.setShortcutId("Settings")
.setShortcutInfo(shortcutInfo)
.setBubbleMetadata(bubble)
And my ShortcutInfoCompat.Builder:
val shortcutInfo = ShortcutInfoCompat.Builder(this, SHORTCUT_ID)
.setLongLived(true)
.setShortLabel("Settings")
.setIntent(Intent(Settings.ACTION_SETTINGS))
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_launcher_foreground))
.build()
ShortCutManagerCompat with pushdynamicshortcut returns:
Unresolved reference: pushDynamicShortcut
I Copy/Pasted code from this:
Gitlab
Thanks.

I added mutableListOf for ShortcutInfo. So, working example:
private var channelCreated = false
private val notifId = 1337
private val notifChannel = "Bubble Manager"
private val shortcutId = "Bubble Manager"
val bubble = showBubble()
#RequiresApi(Build.VERSION_CODES.R)
private fun buildBubbleNotification(appContext: Context): Notification {
val pi = PendingIntent.getActivity(
appContext,
0,
Intent(appContext, BubbleActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
val bubble = NotificationCompat.BubbleMetadata.Builder()
.setDesiredHeight(4000)
.setIcon(IconCompat.createWithResource(appContext, R.drawable.ic_logo_bubble))
.setIntent(pi)
.apply { setAutoExpandBubble(true); setSuppressNotification(true) }
.build()
ShortcutManagerCompat.addDynamicShortcuts(
context, mutableListOf(
ShortcutInfoCompat.Builder(context, shortcutId)
.setLongLived(true)
.setShortLabel("Bubble Manager")
.setIntent(Intent(Settings.ACTION_SETTINGS))
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_logo_bubble))
.build()
)
)
val builder = NotificationCompat.Builder(
appContext,
notifChannel
)
.setSmallIcon(R.drawable.ic_logo_bubble)
.setContentTitle("Title")
.setShortcutId("Bubble Manager")
.setShortcutId(shortcutId)
.setBubbleMetadata(bubble)
val person = Person.Builder()
.setBot(true)
.setName("A Bubble Bot")
.setImportant(true)
.build()
val style = NotificationCompat.MessagingStyle(person)
.setConversationTitle("Bubble Manager")
style.addMessage("It's Bubble Manager", System.currentTimeMillis(), person)
builder.setStyle(style)
return builder.build()
}
#RequiresApi(Build.VERSION_CODES.R)
fun showBubble() {
NotificationManagerCompat.from(context).let { mgr ->
if (!channelCreated) {
mgr.createNotificationChannel(
NotificationChannel(
notifChannel,
"Whatever",
NotificationManager.IMPORTANCE_DEFAULT
)
)
channelCreated = true
}
mgr.notify(notifId, buildBubbleNotification(context))
}
}

Related

Kotlin MVVM, How to get the latest value from Entity in ViewModel?

I have created an app where I try to insert a record with the latest order number increased by one.
The main function is triggered from Activity, however, the whole process is in my ViewModel.
Issue no 1, After I insert a new record the order by number is not updated.
Issue no 2, When I insert first record the order by number is null, for that reason I am checking for null and setting the value to 0.
My goal here is to get the latest order_by number from Entity in my ViewModel, increased by 1 and add that new number to my new record using fun addTestData(..).
Entity:
#Entity(tableName = "word_table")
data class Word(
#ColumnInfo(name = "id") val id: Int,
#ColumnInfo(name = "word") val word: String,
#ColumnInfo(name = "order_by") val orderBy: Int
Dao:
#Query("SELECT order_by FROM word_table ORDER BY order_by DESC LIMIT 1")
suspend fun getHighestOrderId(): Int
Repository:
#Suppress("RedundantSuspendModifier")
#WorkerThread
suspend fun getHighestOrderId(): Int {
return wordDao.getHighestOrderId()
}
ViewModel:
private var _highestOrderId = MutableLiveData<Int>()
val highestOrderId: LiveData<Int> = _highestOrderId
fun getHighestOrderId() = viewModelScope.launch {
val highestOrderId = repository.getHighestOrderId()
_highestOrderId.postValue(highestOrderId)
}
fun addTestData(text: String) {
for (i in 0..1500) {
getHighestOrderId()
var highestNo = 0
val highestOrderId = highestOrderId.value
if (highestOrderId == null) {
highestNo = 0
} else {
highestNo = highestOrderId
}
val addNumber = highestNo + 1
val word2 = Word(0, text + "_" + addNumber,addNumber)
insertWord(word2)
}
}
Activity:
wordViewModel.addTestData(text)

How to crop image with known path based on user selection Android Studio (Ucrop or another library)

I've a question, how can i crop an image if i know the imagePath? I know the imagePath, because the user selects an image from the gallery that we provide.
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()){ uri ->
val inputUri = uri
val outputUri = File(filesDir,"croppedImage.jpg").toUri()
val listUri = listOf<Uri>(inputUri,outputUri)
cropImage.launch(listUri)
}
private val uCropContract = object: ActivityResultContract<List<Uri>,Uri>(){
override fun createIntent(context: Context, input: List<Uri>): Intent {
val inputUri = input[0]
val outputUri = input[1]
val uCrop = UCrop.of(inputUri, outputUri)
.withAspectRatio(5f,5f)
.withMaxResultSize(1080,1080)
return uCrop.getIntent(context)
}
override fun parseResult(resultCode: Int, intent: Intent?): Uri {
return UCrop.getOutput(intent!!)!!
}
}
private val cropImage = registerForActivityResult(uCropContract){ uri ->
binding.imvImageAdded.setImageURI(uri)
}

How to return result from dto?

I'm trying to map entities to dtos and return a result, but it return as null for some reason. What am I doing wrong?
#PutMapping("/contract")
fun getContract(#RequestParam itemId: Int, #RequestParam id: Int): InventoryItemDTO {
var item: InventoryItem = inventoryItemService.getInventoryItemById(itemId)
val i = convertToItemDTO(item)
var con = contractService.getContractById(id)
val c = convertToContractDTO(con)
item.contract = con
i.contractDTO = c
//inventoryItemService.saveInventoryItem(i)
return i
}
fun convertToItemDTO(item: InventoryItem): InventoryItemDTO {
val itemDTO = modelMapper.map(item, InventoryItemDTO::class.java)
itemDTO.contractDTO = convertToContractDTO(item.contract!!)
return itemDTO
}
fun convertToContractDTO(contract: Contract): ContractDTO {
return modelMapper.map(contract, ContractDTO::class.java)
}

How to mirror dragonbones animation?

I make KorGE game with dragonbone animation. How to mirror this dragonbones animation? I want to character look to the right instead of the left:)
val factory = KorgeDbFactory()
val skeDeferred = asyncImmediately { Json.parse(resourcesVfs["Ubbie/Ubbie_ske.json"].readString())!! }
val texDeferred = asyncImmediately { resourcesVfs["Ubbie/Ubbie_tex.json"].readString() }
val imgDeferred = asyncImmediately { resourcesVfs["Ubbie/Ubbie_tex.png"].readBitmap().mipmaps() }
factory.parseDragonBonesData(skeDeferred.await())
factory.parseTextureAtlasData(Json.parse(texDeferred.await())!!, imgDeferred.await())
val armatureDisplay = factory.buildArmatureDisplay("ubbie")!!.position(600, 720).scale(1)
armatureDisplay.animation.play("walk")
addUpdater {
this += armatureDisplay
}
SCALE_X = -1 gives mirror effect
val SCALE_X=-1
val SCALE_Y=1
...
val armatureDisplay = factory.buildArmatureDisplay("ubbie")!!.position(600, 720).scale(SCALE_X, SCALE_Y)

annotation macro that rewrites and impls a trait, generics not processed correctly

I am writing a macro that needs to create a class that rewrites a trait, having the same methods/args of the trait but different return type.
So say we got:
trait MyTrait[T]
{
def x(t1: T)(t2: T): T
}
#AnnProxy
class MyClass[T] extends MyTrait[T]
MyClass will be rewritten to:
class MyClass[T] {
def x(t1: T)(t2: T): R[T]
}
(so x will now return R[T] instead of T)
I wrote the macro and debugging it, it produces this code:
Expr[Any](class MyClass[T] extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def x(t1: T)(t2: T): macrotests.R[T] = $qmark$qmark$qmark
})
#AnnProxy
As you see the signature seems ok. But when trying to use the macro, I get a compilation error:
val my = new MyClass[Int]
my.x(5)(6)
Error:(14, 7) type mismatch;
found : Int(5)
required: T
x.x(5)(6)
^
So it seems the method's generic T is not the same as the class [T]. Any ideas how to fix?
This is my macro so far. I am not any good with macros (coin'd this up with a lot of help from stackoverflow), but this is the current state:
#compileTimeOnly("enable macro paradise to expand macro annotations")
class AnnProxy extends StaticAnnotation
{
def macroTransform(annottees: Any*): Any = macro IdentityMacro.impl
}
trait R[T]
object IdentityMacro
{
private val SDKClasses = Set("java.lang.Object", "scala.Any")
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
def showInfo(s: String) = c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)
val classDef = annottees.map(_.tree).head.asInstanceOf[ClassDef]
val clazz = c.typecheck(classDef).symbol.asClass
val tparams = clazz.typeParams
val baseClasses = clazz.baseClasses.tail.filter(clz => !SDKClasses(clz.fullName))
val methods = baseClasses.flatMap {
base =>
base.info.decls.filter(d => d.isMethod && d.isPublic).map { decl =>
val termName = decl.name.toTermName
val method = decl.asMethod
val params = method.paramLists.map(_.map {
s =>
val vd = internal.valDef(s)
val f = tparams.find(_.name == vd.tpt.symbol.name)
val sym = if (f.nonEmpty) f.get else vd.tpt.symbol
q"val ${vd.name} : $sym "
})
val paramVars = method.paramLists.flatMap(_.map(_.name))
q""" def $termName (...$params)(timeout:scala.concurrent.duration.FiniteDuration) : macrotests.R[${method.returnType}] = {
???
}"""
}
}
val cde = c.Expr[Any] {
q"""
class ${classDef.name} [..${classDef.tparams}] {
..$methods
}
"""
}
showInfo(show(cde))
cde
}
}
EDIT: I managed to work around by building the class as a string and then using c.parse to compile it. Feels like a hack but it works. There must be a better way by manipulating the tree.
package macrotests
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
#compileTimeOnly("enable macro paradise to expand macro annotations")
class AnnProxy extends StaticAnnotation
{
def macroTransform(annottees: Any*): Any = macro AnnProxyMacro.impl
}
trait R[T]
trait Remote[T]
object AnnProxyMacro
{
private val SDKClasses = Set("java.lang.Object", "scala.Any")
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val classDef = annottees.map(_.tree).head.asInstanceOf[ClassDef]
val clazz = c.typecheck(classDef).symbol.asClass
val baseClasses = clazz.baseClasses.tail.filter(clz => !SDKClasses(clz.fullName))
val methods = baseClasses.flatMap {
base =>
base.info.decls.filter(d => d.isMethod && d.isPublic).map { decl =>
val termName = decl.name.toTermName
val method = decl.asMethod
val params = method.paramLists.map(_.map {
s =>
val vd = internal.valDef(s)
val tq = vd.tpt
s"${vd.name} : $tq"
})
val paramVars = method.paramLists.flatMap(_.map(_.name))
val paramVarsArray = paramVars.mkString("Array(", ",", ")")
val paramsStr = params.map(_.mkString("(", ",", ")")).mkString(" ")
val retTpe = method.returnType.typeArgs.mkString("-unexpected-")
s""" def $termName $paramsStr (timeout:scala.concurrent.duration.FiniteDuration) : macrotests.Remote[$retTpe] = {
println($paramVarsArray.toList)
new macrotests.Remote[$retTpe] {}
}"""
}
}
val tparams = clazz.typeParams.map(_.name)
val tparamsStr = if (tparams.isEmpty) "" else tparams.mkString("[", ",", "]")
val code =
s"""
|class ${classDef.name}$tparamsStr (x:Int) {
|${methods.mkString("\n")}
|}
""".stripMargin
// print(code)
val cde = c.Expr[Any](c.parse(code))
cde
}
}
the code is very long , you can look at the github: https://github.com/1178615156/scala-macro-example/blob/master/stackoverflow/src/main/scala/so/AnnotationWithTrait.scala
import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
/**
* Created by yu jie shui on 2015/12/2.
*/
class AnnotationWithTrait extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro AnnotationWithTraitImpl.apply
}
class AnnotationWithTraitImpl(val c: Context) {
import c.universe._
val SDKClasses = Set("java.lang.Object", "scala.Any")
def showInfo(s: String) = c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)
def apply(annottees: c.Expr[Any]*) = {
val classDef = annottees.map(_.tree).head.asInstanceOf[ClassDef]
val superClassSymbol= c.typecheck(classDef).symbol.asClass.baseClasses.tail
.filterNot(e => SDKClasses.contains(e.fullName)).reverse
val superClassTree= classDef match {
case q"$mod class $name[..$t](..$params) extends ..$superClass { ..$body }" =>
(superClass: List[Tree]).filterNot(e =>
typeOf[Object].members.exists(_.name == e.children.head.toString())
)
}
showInfo(show(superClassSymbol))
showInfo(show(superClassTree))
val impl = q"private[this] object ${TermName("impl")} extends ..${superClassTree}"
//
//get super class all can call method
val methods = superClassSymbol.map(_.info.members
.filterNot(_.isConstructor)
.filterNot(e => typeOf[Object].members.exists(_.name == e.name)).map(_.asMethod)).toList
case class ReplaceTypeParams(from: String, to: String)
type ClassReplace = List[ReplaceTypeParams]
//trait a[A]
//class b[B] extends a[B]
//need replace type params A to B
val classReplaceList: List[ClassReplace] = superClassTree zip superClassSymbol map {
case (superClassTree, superClassSymbol) =>
superClassSymbol.asClass.typeParams.map(_.name) zip superClassTree.children.tail map
(e => ReplaceTypeParams(e._1.toString, e._2.toString()))
}
val out = classReplaceList zip methods map {
case (classReplace, func) =>
func map { e => {
val funcName = e.name
val funcTypeParams = e.typeParams.map(_.name.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM), TypeName(name), List(), TypeBoundsTree(EmptyTree, EmptyTree))
})
val funcParams = e.paramLists.map(_.map(e => q"${e.name.toTermName}:${
TypeName(
classReplace.find(_.from == e.info.toString).map(_.to).getOrElse(e.info.toString)
)} "))
val funcResultType = TypeName(
classReplace.find(_.from == e.returnType.toString).map(_.to).getOrElse(e.info.toString)
)
q"""
def ${funcName}[..${funcTypeParams}](...$funcParams):${funcResultType}=
impl.${funcName}[..${funcTypeParams}](...$funcParams)
"""
}
}
}
showInfo(show(out))
q"""
class ${classDef.name}[..${classDef.tparams}]{
$impl
..${out.flatten}
}
"""
}
}
test
trait MyTrait[MT1] {
def x(t1: MT1)(t2: MT1): MT1 = t1
}
trait MyTrait2[MT2] {
def t(t2: MT2): MT2 = t2
}
#AnnotationWithTrait
class MyClass[MCT1, MCT2] extends MyTrait[MCT1] with MyTrait2[MCT2]
object AnnotationWithTraitUsing extends App {
assert(new MyClass[Int, String].x(1)(2) == 1)
assert(new MyClass[Int, String].t("aaa") == "aaa")
}

Resources