Problem with Kotlin Duration in Android Studio - android

I'm new with Android Studio and Kotlin and I have some trouble with Kotlin Duration. When I try to do following in my code:
val test: Duration = Duration.parse(value = timeClose)
I get this error message:
This declaration needs opt-in. Its usage must be marked with '#kotlin.time.ExperimentalTime' or '#OptIn(kotlin.time.ExperimentalTime::class)'
I use Android Studio Chipmunk 2021.2.1 Patch 1 with Kotlin 212-1.7.10
How can I solve my problem?

Do what the error is telling you to do: mark it with one of the suggestions.
#kotlin.time.ExperimentalTime
val test: Duration = Duration.parse(value = timeClose)
or
#OptIn(kotlin.time.ExperimentalTime::class)
val test: Duration = Duration.parse(value = timeClose)
The reason you have to do this is that the Duration class is in the ExperimentalTime package, which means that this is an experimental preview, as the documentation states:
Note that this API is in a preview state and has a very high chance of being changed in the future. Do not use it if you develop a library since your library will become binary incompatible with the future versions of the standard library.

Related

Cannot resolve symbol 'EInvoice' in using EInvoice API in Android Studio

I'm new to Android Studio and is trying to create a app for recording invoice relative information.
Currently I'm trying to use "EInvoice" API shared in Github but stuck in object declaration.
Refer to author's advice, I succeeded to add dependency to Android Studio, but always failed in object declaration:
val invSdk = EInvoice("API_KEY")
It seems that Android Studio can't recognize "val" and "EInvoice".
Then I try to declare it with common method:
private EInvoice Invoice=new EInvoice();
Unfortunately Android Studio always failed to compile with error "cannot resolve symbol 'EInvoice' even if I try to add below import code:
import com.github.kevinchung0921:einvoice_sdk:v1.3
Can you please be kind to suggest correct method to declare the external-imported-API object and use functions such as:
val detail = invSdk.getCarrierDetail(header, USER_BARCODE, USER_PASS)
Thanks a lot for your reading and further help.
cannot resolve Error

How to resolve "Obsolete custom lint check" for my custom IssueRegistry written in Kotlin and make it work (Android)

I am trying to implement custom lint checks (using Kotlin). I have set up a module for my custom checks and added classes to test my first lew lint check, mostly following these two tutorials here and here.
So I now have a module, I have a custom IssueRegistry, I've created an issue and a Detector class for it. So far it seems complete. I've added a test to check if my lint check works and it looks alright.
I have added my module to the project by referencing it in settings.gradle like this: include ':app', ':somemodule', ':mylintmodule'
Now if I run the linter using ./gradlew lint I get a lint result file telling me this:
Lint found an issue registry (com.myproject.mylintmodule) which requires a newer API level. That means that the custom lint checks are intended for a newer lint version; please upgrade
Lint can be extended with "custom checks": additional checks implemented by developers and libraries to for example enforce specific API usages required by a library or a company coding style guideline.
The Lint APIs are not yet stable, so these checks may either cause a performance degradation, or stop working, or provide wrong results.
This warning flags custom lint checks that are found to be using obsolete APIs and will need to be updated to run in the current lint environment.
It may also flag issues found to be using a newer version of the API, meaning that you need to use a newer version of lint (or Android Studio or Gradle plugin etc) to work with these checks.
To suppress this error, use the issue id "ObsoleteLintCustomCheck" as explained in the Suppressing Warnings and Errors section.
So it tells me that I am using a newer API verion in my custom lint check, right? This is my custom IssueRegistry (minus some parts not relevant for this problem):
class MyCustomIssueRegistry : IssueRegistry() {
override val issues: List<Issue>
get() = listOf(ISSUE_NAMING_PATTERN)
override val api: Int = com.android.tools.lint.detector.api.CURRENT_API
override val minApi: Int = 1
}
From googling this problem and finding this issue I figured I have to override and set the right API version (and maybe the min API?) by overriding these properties like I did above (this version is my last attempt, directly taken from that issue).
So this property can be set to values between -1 and 5, meaning this (taken right out of the lint.detector.api class):
/** Describes the given API level */
fun describeApi(api: Int): String {
return when (api) {
5 -> "3.5+" // 3.5.0-alpha07
4 -> "3.4" // 3.4.0-alpha03
3 -> "3.3" // 3.3.0-alpha12
2 -> "3.2" // 3.2.0-alpha07
1 -> "3.1" // Initial; 3.1.0-alpha4
0 -> "3.0 and older"
-1 -> "Not specified"
else -> "Future: $api"
}
I have tried all of them, plus the one above adding a minApi override too, and I keep getting the exact same result for each of them.
Also I am unable to locate what other API version this is compared with. Is there a place where this is set for the regular linter in an Android project?
It's also unclear to me what I have to do to make sure my changes got applied - is it enough to change some code, then run lint, or do I have to compile the project first, or build & clean?
Following the tutorials, I added my custom lint check by adding this to the app's build.gradle: lintChecks project(":mylintmodule")
Is that even right? The API issue on my registry class shows up no matter if my lint check is referenced (and hopefully used) like that or not. I have also tried the other method described in the first tutorial, adding this task to the linter module build.gradle:
defaultTasks 'assemble'
task copyLintJar(type: Copy) {
description = 'Copies the lint jar file into the {user.home}/.android/lint folder.'
from('build/libs/')
into(System.getProperty("user.home") + '/.android/lint')
include("*.jar")
}
// Runs the copyLintJar task after build has completed.
build.finalizedBy(copyLintJar)
But since I can't figure out how to see if my custom checks are actually run, I don't know if that works as intended either.
So how do I get this warning resolved (since I interpret the text as "As long as the versions don't match I will not try to run your lint check"), and how can I make sure my lint check is actually run by the linter?

Cross compile platforms

I wanted to create sbt cross platforms (Hello world app ) including JVM , Scala Native , Android and scalajs , I have succeed in compiling all of them except the android and this is my build.sbt:
name := "Cross-Platforms-ScalaNative-JVM"
import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType}
val sharedSettings = Seq(scalaVersion := "2.11.12")
lazy val bar =
// select supported platforms
crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Full)
.settings(sharedSettings)
.jsSettings(
libraryDependencies += "org.querki" %%% "jquery-facade" % "1.2")
.jvmSettings(/* ... */)
.nativeSettings(/* ... */)
lazy val barJS = bar.js
lazy val barJVM = bar.jvm
lazy val barNative = bar.native
My question how I can create an android platform in this project; what changes should be to my SBT?
Android build is basically an JVM build with an extra steps - taking JVM bytecode, optionally running proguard to minimize code and compiling it into Android format.
Here you have a lot of information about how to setup normal android build in sbt: https://scala-android.org/quickstart/.
The difference would be by applying androidBuild (and all Android-related settings) only to JVM projects:
val myProjectJVM = myProject.jvm
.settings(androidBuild: _*)
However, considering that Android build and normal Scala build will look differently (as normal JVM application has architecturally little to do with Android apps - e.g. Main.main(Array[String]) vs Android fragments and services) it would be a better idea to have a module for some shared JVM code and a dedicated projects for the platform-specific parts:
val commonJVM = myProject.jvm
val myProjectJVM = project.in(file("java-specific"))
.dependsOn(commonJVM)
val myProjectAndroid = project.in(file("android-specific"))
.settings(androidBuild)
.dependsOn(commonJVM)
That architectural difference is most likely a reason why nobody even considers making Android a fourth option in a cross project - you have a different runtime dependencies, a different way to start the application, so you would have more parts of the code that differ than in common. Submodules with code dedicated to platform depending on common dependency (even cross-compiled one) is a better idea.

refer aosp functions in Android Core App using gradle

How to refer aosp hidden methods in core android app using gradle build system. I am referring framework and other jars from out folder but unable to access hidden API. Is there any way to access hidden methods.
There are a couple ways.
Android Hidden API
As long as you're fine targeting API 27 (there's no API 28 release as of writing this) this way works great. You can directly call the hidden methods with proper code completion and everything.
Note: As of writing this, you'll need to set your Gradle classpath to 3.1.4. 3.2.0 adds some sort of integrity check that breaks builds when using a modified framework JAR.
Use reflection
It's not ideal, but it'll work if you want to target API 28, or you want to use Gradle 3.2.0.
Example (Kotlin):
val IWindowManager = Class.forName("android.view.IWindowManager")
val IWindowManagerStub = Class.forName("android.view.IWindowManager\$Stub")
val ServiceManager = Class.forName("android.os.ServiceManager")
val binder = ServiceManager.getMethod("checkService", String::class.java).invoke(null, Context.WINDOW_SERVICE)
val iWindowManagerInstance = IWindowManagerStub.getMethod("asInterface", Binder::class.java).invoke(null, binder)
val hasNavBar = IWindowManager.getMethod("hasNavigationBar").invoke(iWindowManagerInstance) as Boolean

Runtime error using Xamarin Android with F# and ReactiveUI

I have created a Xamarin Android project that is using F# and ReactiveUI.
When loading my Dashboard, I encounter a runtime exception (of type MissingMethodException) on the inherit line of this code snippet:
type DashboardViewModel(?host: IScreen) =
inherit ReactiveViewModel()
let host = LocateIfNone host
member __.Title with get() = "Dashboard"
interface IRoutableViewModel with
member __.HostScreen = host
member __.UrlPathSegment = "Dashboard"
The error message reads
Method 'Microsoft.FSharp.Quotations.FSharpExpr.Deserialize40' not found.
The ReactiveViewModel type is a thin wrapper around ReactiveObject:
type ReactiveViewModel() as this =
inherit ReactiveObject()
let mutable message = noMessage
let uiContext = SynchronizationContext.Current
member __.SyncContext with get() = uiContext
member this.Message
with get() = message
and set(value) =
this.RaiseAndSetIfChanged(&message, value, "Message") |> ignore
if message <> noMessage then this.RaiseAndSetIfChanged(&message, noMessage, "Message") |> ignore
member val MessageSent =
this.WhenAnyValue(toLinq <# fun vm -> vm.Message #>).ObserveOn(RxApp.MainThreadScheduler).Where(fun m -> m <> noMessage) with get
The project is open source: at the moment, it contains very little content. It can be found at https://github.com/SpiegelSoft/Astrid.
I have submitted a bug on the Xamarin bug tracker: https://bugzilla.xamarin.com/show_bug.cgi?id=51000
Are there any known fixes I can implement myself, so that I can close the bug of my own accord?
UPDATE 1
I've been investigating this issue this weekend.
The FSharp.Core version that is loaded is stuck on the obsolete version 2.3.98.1. This corresponds to the FSharp.Core.dll file in
C:\Program Files (x86)\Reference
Assemblies\Microsoft\Framework\MonoAndroid\v1.0
I have tried to remove this version and load the NuGet package FSharp.Core; however, when I build the Android project, the path always reverts to the obsolete file in the Reference Assemblies path.
Is there a way to override this behaviour?
UPDATE 2
Replacing the FSharp.Core.dll file in the Reference Assemblies path fixes the issue, but this is a very unsatisfactory sticking plaster, which I can't ask my users to apply. Ideally, I would like to find a way to prevent the .Droid project from loading FSharp.Core from the GAC rather than the NuGet package.
I just ran into a very similar issue the other day. My android app had a reference to a Profile7 F# PCL library, which made use of List.unfold, which I believe was introduced in F# 4. When I used the library in my app, I saw a MissingMethodException similar to what you are seeing. The version of FSharp.Core that Xamarin references by default when creating a new Android app didn't have this newer method. I got around it by editing the .fsproj file for the app to remove the original reference to FSharp.Core, and replaced it with a reference to the newer version ( I copy/pasted the tag from the PCL .fsproj file). It looks something like this:
<Reference Include="FSharp.Core">
<Name>FSharp.Core</Name>
<Private>True</Private>
<AssemblyName>FSharp.Core.dll</AssemblyName>
<HintPath>$(MSBuildExtensionsPath32)\..\Reference Assemblies\Microsoft\FSharp\.NETCore\$(TargetFSharpCoreVersion)\FSharp.Core.dll</HintPath>
</Reference>
I was suprised to find that this seems to have fixed the problem for me. I'm not sure if I'll run into other issues down the line, but it may be worth trying this if you havent already.
UPDATE If this doesn't work immediately, follow the sequence of steps in Rob Lyndon's answer.
It appears that this has been fixed by the GitHub commit
https://github.com/xamarin/xamarin-android/commit/df41af046000556ed82f638e8041b7f718966a92
which removes FSharp.Core from the list of framework assemblies, and allows the project to be built without the NuGet FSharp.Core assembly being replaced.
Until this fix is released into the SDK, there is a workaround. The answer submitted by user3850711 works, but you need to apply the changes in a specific sequence, because otherwise the reference will be overwritten during the build.
Delete the existing reference to FSharp.Core.
Install or reinstall the FSharp.Core NuGet package.
Unload the project and add <HintPath>packages\FSharp.Core.4.0.0.1\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll</HintPath> to the FSharp.Core project reference.

Categories

Resources