I am attempting to create an Android application using Scala 2.9.2. So far, I have got everything to compile.
However, I am running into problems when I perform the following in my activity:
override def onCreateDialog(id: Int) {
The compiler complains of an incompatible type as Activity.onCreateDialog() takes a primitive int yet I am passing a scala.Int.
The folowing is the compilation error:
error: overriding method onCreateDialog in class Activity of type (x$1: Int)android.app.Dialog;
[INFO] method onCreateDialog has incompatible type
[INFO] override def onCreateDialog(id: Int) {
[INFO] ^
[ERROR] one error found
I thought these would be compatible.
Can anyone advise how to get around this problem?
The following is for Scala 2.10, but I think that the cause of the error is exactly the same for Scala 2.9.x.
By the way, the onCreateDialog(int) method from the type Activity is deprecated, but it's beside the point.
Now, I'm not a Scala expert by any means, but from what I have noticed, functions that do not return anything tend do look like def fun(arg) {}, and ones that do: def fun(arg) = {}. Notice the =. You can also spell out the return type if you want.
So I tried to override the method you mention, and here's the (trivial) implementation:
override def onCreateDialog(id : Int) = {
super.onCreateDialog(id)
}
And it compiles and runs just fine. When you remove the =, you'll get the error you have right now:
overriding method onCreateDialog in class Activity of type (x$1: Int)android.app.Dialog; method onCreateDialog has
incompatible type
The whole MainActivity:
class MainActivity extends Activity {
override def onCreate(savedInstanceState : Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_activity)
}
override def onCreateDialog(id : Int) = {
super.onCreateDialog(id)
}
}
Notes: I'm using ADT with bundled Eclipse (Juno), created a default Android project, including Scala-IDE (Scala nature) and AndroidProguardScala (AndroidProguardScala nature)
Related
I have a simple result class called Outcome which is sealed and consists of three subclasses: Waiting, Success and Failure:
sealed class Outcome<out T> {
object Waiting : Outcome<Nothing>()
class Success<T>(val data: T) : Outcome<T>()
open class Failure : Outcome<Nothing>()
}
Now I want to use a when statement to check which type a generic Outcome is, however Android Studio (and specifically Android Studio, IntelliJ IDEA doesn't have this issue) seems to think that it is not exhaustive and gives the warning:
'when' expression on sealed classes is recommended to be exhaustive, add 'is Failure', 'is Success', 'Waiting' branches or 'else' branch
However the when definitely is exhaustive:
when (o) {
is Outcome.Failure -> TODO()
is Outcome.Success -> TODO()
Outcome.Waiting -> TODO()
}
and even when I ask for the remaining branches to be added, it simply adds a copy of what I already have and still yields the same error:
when (o) {
is Outcome.Failure -> TODO()
is Outcome.Success -> TODO()
Outcome.Waiting -> TODO()
is Outcome.Failure -> TODO()
is Outcome.Success -> TODO()
Outcome.Waiting -> TODO()
}
This isn't a massive issue as it is only a warning and doesn't cause any actual problems. However I would like to know whether this is an inference bug or if it is something related to my design.
Note: My Android Studio plugin version is 1.4.32-release-Studio4.1-1 and I have tried this with a completely new project and got the same results.
This issue has now been rectified since upgrading to Kotlin 1.5 (specifically 202-1.5.0-release-764-AS8194.7) so it looks like it must have just been an inference bug.
I build an Android Library (using Kotlin) and I have a class containing some constants.
class LibraryClass {
companion object {
#JVMStatic
val MY_CONSTANT = "value"
}
}
I generate an .aar file using the assembleRelease Gradle task, then I import the .aar file into another app.
The other app also uses kotlin, when I reference the constant inside the companion object, It can't find it.
if(myVariable == LibraryClass.MY_CONSTANT) {
foo()
}
The IDE itself can't find it, it just says:
Unresolved reference: MY_CONSTANT
And when I use the IntelliJ decompiler, the constant is not there, not even using LibraryClass.Companion, it can't even find the reference to the Companion object.
How can I fix this?
I am currently trying to write a custom lint check that I am working on. I have created a separate java project and included it as a jar.
My problem is that no matter what, it seems that my custom check is not being run when analyzing my code base.
I've included a registry
class MyIssueRegistry : IssueRegistry() {
override val issues: List<Issue>
get() = listOf(MyIssues.ISSUE_PATTERN)
}
And a detector
class MyIssueDetector : Detector(), Detector.UastScanner {
override fun getApplicableUastTypes() = listOf(UClass::class.java)
override fun createUastHandler(context: JavaContext) =
MyIssueDetector(context)
class MyIssueDetector(private val context: JavaContext) : UElementHandler() {
override fun visitClass(node: UClass) {
context.report(MyIssues.ISSUE_PATTERN, context.getNameLocation(node), "This is just a test")
}
}
}
I've also added attributes("Lint-Registry-v2": "com.pathto.lint.MyIssueRegistry") to my java project's gradle and included it in my app gradle as lintChecks project(":lint")
AFAIK this topic- My code should be throwing a warning everytime it reads a class, but the lint check is not being ran. Is there a step I am missing?
first, check your lint.jar is placed on the right path. my path is ~/.android/lint/lint.jar.
then execute command '$ANDROID_HOME/tools/bin/lint --show | grep 'your issue name'' to check your custom lint is attached or not.
and then you can put some log to your custom lint implementation just like using "System.out.println()"
hope this can help u.
The app defines constants in a Kotlin singleton object:
#file:JvmName("APIConstants")
package com.myapp.api
object APIConstants {
const val HTTP_RESPONSE_CODE_NOT_AUTHORIZED = 401
etc....
}
They are then used in another class:
import com.myapp.api.APIConstants.HTTP_RESPONSE_CODE_NOT_AUTHORIZED
etc ...
class API {
private fun returnBadResponse(response: Response<*>, callback: ApiAuthListener<*>) {
if (response.code() == HTTP_RESPONSE_CODE_NOT_AUTHORIZED) {
callback.onBadAuthToken()
} else {
callback.onFailure(response.message(), getServerError(response))
}
}
In this class Android Studio (3.0 beta) provided a hint to add the import for the constant, and it does not give any indication of a problem (no red underlines etc, and the constant reference in the method is shown in purple italic text indicating it has been resolved) but when I build the project I get this:
Error: Unresolved reference: HTTP_RESPONSE_CODE_NOT_AUTHORIZED
I've tried clearing the IDE cache and restarting it, and doing a clean build, which make no difference. I've tried removing the #JvmName annotation and even placing the const values in the root of the file with no containing object but neither allows a build.
Why is the class failing to reference the constant, especially when the IDE strongly suggests it can resolve it?
And the solution is.... to make very sure all Kotlin source files have a .kt file extension! In this case the APIConstants file was called "APIConstants" and not "APIConstants.kt" which appears to mean the IDE was able to resolve references based on the content of the file, but the build tools could not. Confusingly Android Studio showed a Kotlin K icon on the filename despite the lack of a .kt extension.
I'm trying to use the scala-reflect package for android development.
I have added the scala-reflect dependency in my build.sbt:
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.8"
but I get an exception:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/rmi/Remote;
at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass$lzycompute(Definitions.scala:370)
at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass(Definitions.scala:370)
at scala.reflect.runtime.JavaUniverseForce$class.force(JavaUniverseForce.scala:255)
at scala.reflect.runtime.JavaUniverse.force(JavaUniverse.scala:16)
at scala.reflect.runtime.JavaUniverse.init(JavaUniverse.scala:147)
at scala.reflect.runtime.JavaUniverse.<init>(JavaUniverse.scala:78)
at scala.reflect.runtime.package$.universe$lzycompute(package.scala:17)
at scala.reflect.runtime.package$.universe(package.scala:17)
I have tried to add the java source of java.rmi.Remote and java.rmi.RemoteException and built the project with android:package --core-library (because sbt has not found the dexCoreLibrary option) , it builded successfully, but I got the runtime error.
So, is it possible to add the java.rmi dependency otherwise, that scala.reflect can use it?
I'm using the scala.reflect library in the context of an implementation of a method Option.orDefault:
class RichOption[+A : TypeTag](val delegate: Option[A]) {
def orDefault : A = delegate.getOrElse {
delegate match {
case t if typeOf[A] <:< typeOf[Int] => 0.asInstanceOf
case _ => throw new IllegalAccessException("there is no default value for this type.")
}
}
}
If you know a better implementation for Option.orDefault
(possibly without scala.reflect), please let me know.
Much better:
case class Default[A](value: A)
object Default {
implicit val intDefault: Default[Int] = Default(0)
// other Default implementations
}
class RichOption[+A](val delegate: Option[A])(implicit d: Default[A]) {
def orDefault : A = delegate.getOrElse(d.value)
}
You get a compilation error instead of a runtime error if used with a type which doesn't have a defined default value, no complex matching, no need for a large dependency, etc.