So, I wanted to implement a simple database handler class for my Android Studio project with Kotlin. Little did I know when I eye-rolled towards my "what even is kotlin" developer mates, that this hipster choice would lead me to lengthy damnation.
I decided to start out by copy-pasting the code Google suggests for a DB Helper utilizing the SQLiteOpenHelper class.
Naturally, I started getting this unreasonable error
for each of the closing brackets } in 3 different methods containing what looked like perfectly valid syntax.
Of course, I spent over a day checking every single piece of annoying Gradle build property that seems to be there only to increase the chances of something being off, as if it were a perfectly designed developer-Limbo build system from Hell. But every little check was to no avail, as I had no build errors and the "Expecting member" errors kept showing up.
Decided not to quit however, I even attempted to change my implementation to use the more Kotlin-friendly anko.db route, full code below.
package com.example.john.myapplication
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import org.jetbrains.anko.db.*
class DBHandler(context: Context) : ManagedSQLiteOpenHelper(context, "POIEncounters", null, 1) {
override fun onCreate(db: SQLiteDatabase?) {
db?.createTable("Encounter", true, "id" to INTEGER + PRIMARY_KEY + UNIQUE, "Name" to TEXT)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db?.dropTable("Encounter", true)
}
override fun onDowngrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
onUpgrade(db, oldVersion, newVersion)
}
}
As Divine Order dictates in the Developer Limbo, there was no change at all. Every time I click Build I am fooled by the syntax checker's underhanded reassurances, as the compiler denies my salvation. Even more amazingly. the errors persist even if I comment-out the entire bodies of the overridden methods.
At this point I am so beyond despair that I have fallen to the lowest level of the abyss: rejecting my ego and asking for help.
For those not brave enough to witness the process, TLDR at the end.
The answer is given by my own self, after 3 endless epochs (see: days) in this unbuildable hellish dimension, and written at 3am with the sole company of a bottle of Glenfiddich whisky joined in the dark by the sounds of my demonized keyboard clacking.
The usual suspects of easy-to-miss spelling errors, invalid constructor usage have been discarded over and over as I descend into madness, now fairly certain that even if someone where to copy my exact code, they might not even be getting this error.
I even tried tried downgrading Kotlin itself, in delusional hopes of a bug in its compiler bringing forth all these insistent mutterings of "Expecting declaration"...
In a last insane attempt I even tried importing my code into a different infernal machination of an IDE, just to see if the apocryphal messages would follow me there, in Intellij IDEA...
After one more hour of torment to align the new project's build files and other horrid properties causing minor issues... They did.
I was about to give up and when I spotted this strange, unfamiliar sign on Intellij's syntax checker:
Found byte-order-mark in the middle of a file <...>
SON. OF. A. BENCH.
Now, at this incredibly agonizing part of my journey, much like many other devs living in the blissful heaven-like area of "typing code that is parsed the way you read it", I had no forking idea what a BOM is.
Yet the celestial IDEA even gives us the forbidden, dark knowledge of a wikipedia link, which I followed in foolish innocence, to see a maddening, curious fragment of the cosmos which man was not meant to lay eyes upon...
What the fork.
My fingers trembled and started moving in a feverish climax. I heard myself cackling as I submerged myself in the unreal madness of a last irrational hope...
I deleted the 3 methods. Purged them all an in unholy, functio-cidal frenzy and gazed up the empty class, free of the invisible, sickening infection.
Build. *click* Success.
I rewrote each and every one one of the methods by hand, without copy-pasting or touching any devil-infected piece of vile text, while listening to the fiendish, otherworldly "Dethklok Awaken" calls. And that was it. It worked. I am free, ascending into Elysium, whiskey in one hand and tears dropping to the Flame Below.
Yet, empty and disappointed. For the the cunning shade was not a tangible foe, but an ephemeral force, looming inside the Self...
With this answer, I hope no one has to face the same mistake I did. Not unprepared at least.
TLDR: There was a BOM character that was causing the error. Intellij clarified the cause, while Android Studio didn't. Deleted and re-wrote problematic parts by hand without copy-pasting anything and it worked.
Epilogue: Everyday we stray further from ASCII's light.
Related
I'm repairing my friend's code and got confused.
My friend wants to fetch entered text (in EditText). Seems easy, right? Well, it is but instead of user input, he gets this warning/error:
To be honest I'm not sure how to fix it. He is coding in Kotlin (Android 10).
Activity that contains EditText:
And XML:
This is how it looks when debugging:
The app started working just fine after running "File -> invalidate Cashes/Restart" option, I just don't understand where this warning came from and how to fix it because the error remained unchanged (even though the app works). Do you have an idea how to solve it?
All the best!
fyi lambda expression like setOnClickListener from kotlin is not debuggable, see here.
if you want to debug variables inside setOnClickListener you should use the normal one e.g. setOnClickListener(object: View.OnClickListener {..})
sometimes there will be problem in auto generated binding files, if so it will be solved after invalidate cache and restart ide. sometimes the warning/error show but the project and complied without errors. so no need to worry about that. for next time post the code as code not screen shots.
I understand that the question is regarding evaluating expression, but there is a way you can read variables from your debugger console, even if you're inside an anonymous callback. I found it helpful sometimes. Here are the steps:
First enter debugger mode inside of your anonymous callback,
In your debugger console, look at the right side for "Frames"
Within Frames under , you'll see stack of function execution first top one on the list is the latest:
Click on row(s) below the latest function, until you find an instance of your activity AddInformationActivity. You will see the activity instance on the right side window under Variables. Don't go as far as selecting functions browned out, because those are from internal libraries.
When you see you AddInformationActivity instance, you can expand it and see its variables.
Hope that helps!
It's not a beautiful way, but if you create a method like this:
private fun debug() {
println()
}
and add a breakpoint on the println() it'll capture the activity.
(Don't use TODO as it'll crash the app with a NotImplementedError once called.)
I have this method now in my code all the time to call it whenever I need it.
I know, that question is old, but I just stumbled over it and needed a way.
In my android app I am using Room with sqlcipher library for encrypt/decrypt. Often I see in Crashlytic the following crash:
java.util.concurrent.TimeoutException:
net.sqlcipher.database.SQLiteCompiledSql.finalize() timed out after 10
seconds at sun.misc.Unsafe.park(Native Method) at
java.util.concurrent.locks.LockSupport.park(LockSupport.java:190) at
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:868)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:902)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1227)
at
java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:231)
at
java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:294)
at
net.sqlcipher.database.SQLiteDatabase.lock(SQLiteDatabase.java:567)
at
net.sqlcipher.database.SQLiteCompiledSql.releaseSqlStatement(SQLiteCompiledSql.java:104)
at
net.sqlcipher.database.SQLiteCompiledSql.finalize(SQLiteCompiledSql.java:146)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:289) at
java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:276) at
java.lang.Daemons$Daemon.run(Daemons.java:137) at
java.lang.Thread.run(Thread.java:929)
The line where it crash is SQLiteDatabase.lock() line 567
Previously it was line 566, but in that method I inserted a check: if the database is not open -> return and don't proceed with locking, but it didn't help and the crash appeared again.
I think that this crash may be because the garbage collecting happens when the app is in the background (our app has a foreground service that works all the time). But not sure how to fix it.
As for Room: I don't close it, it is open all the time, because my app works all the time, so need it often. And close it after every query to the database is the bad practice.
I asked the developers of sqlcipher, but they don't know, what can cause this crash. Maybe anybody knows?
I've been seeing this in Crashlytics for quite a while, and seemingly has been able to fix this in the end completely, I'll post the full research here.
Issue
For queries like this one:
#Query("DELETE FROM table WHERE id NOT IN (:ids)")
abstract fun deleteNotInList(ids: List<String>): Int
Room generates code that doesn’t clean cursor and generated statements (on the image below, compare how the method one doesn’t use cursor, and doesn’t call release() methods, compared to the bottom one which calls cursor.close(); method names and queries are slightly different there, cause I simplified the snippets):
In this scenario statements are kept in memory un-released, and the releasing shifts to GC phase, inside finalize() method. And finalize() in SqlCipher (SQLiteCompiledSql) in turn needs to lock the Database in order to release the statement:
Problem is that the Database might be locked for a long transaction for more than 10 sec (or a batch of shorter transactions, awakening order using such locks isn’t guaranteed and isn’t fair).
GC watchdog crashes the thread when it reaches 10/20 seconds depending on the OS/JVM exact version.
Solution
Is to rewrite all DELETE / UPDATE using IN operator with manual raw queries like this:
#RawQuery
abstract fun deleteNotInListRaw(query: SimpleSQLiteQuery): Int
fun deleteNotInList(
ids: List<String>
) {
deleteNotInListRaw(
SimpleSQLiteQuery(
"DELETE FROM table WHERE id NOT IN (${ids.joinToString(prefix = "'", postfix = "'", separator = "','")})"
)
)
}
In this case the query uses cursor and closes it after deletion is done, still locking database but not on GC phase and on the dedicated thread.
P.S.
There’re more stable long term solutions possible but they needs to be implemented on the Room / SqlCipher sides.
In the given state, SqlCipher can be refactored to not lock the database on GC phase. There’s an open issue for that: https://github.com/sqlcipher/android-database-sqlcipher/issues/537
Room should probably fix the codegen and use the query builder and generate statement closure lines, there’s no open issues there, but I’ll double check this thought later and will raise this as an issue with them.
For us this has seemingly solved the issue completely.
Note that all DELETE / UPDATE queries using IN / NOT IN operators and probably some other operators that prevent Room from precompiling the query (due to runtime params) cause this. You can check the codegen to verify that generated code calls either cursor.close() or statement.release()
I have been creating Spinner controls (Combo boxes/Drop downs) in one of my apps, and was surprised to find out how difficult it was to achieve all of the following features:
User facing Strings are externalized, taking advantage of strings.xml internationalisation (I18N) feature of Android.
Spinner selections operate using a System view, which facilitates not having to work with or map Strings to meaningful values (yuck).
User view to System view mapping should be easy, automated and minimal (i.e not hand rolled for every component).
Others have attempted solutions to this, but universally as far as I could see they suffer from one or many of the following problems:
UI code is creeping into their enum class which doesn’t belong there (messy), nearly all existing solutions suffered from this.
Hardcoded User facing Strings in their enum classes. Because these are not externalized you cannot do I18N using the stock Android features.
Authors typically make the Fragment or Activity an OnItemSelectedListener which perpetuates a common problem of inheritance for convenience, where composition is more appropriate.
I have developed my own solution which does this: http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/
My question is, have I missed something? This seems like something that should not have been this hard (which makes me feel like I'm possibly reinventing the wheel).
Below is some example code showing my solution in-use (which is available Apache 2 license from the link above).
String none = getString(R.string.none);
String light = getString(R.string.light);
String medium = getString(R.string.medium);
String strong = getString(R.string.strong);
SpinnerUtil.createNewSpinner(view, R.id.wind, Arrays.asList(none, light, medium, strong), WindLevel.values(),
new SpinnerItemSelectedListener<WindLevel>() {
public void onItemSelected(Spinner item, WindLevel value) {
// Take whatever action you wish to here.
}});
I would just use ArrayAdapter<WindLevel>. Yes, you created a custom typed listener, but the regular event listener gets the position and can call getItem() on the ArrayAdapter<WindLevel> to get a WindLevel properly typed.
IMHO, the vast majority of Spinner widgets will be populated with material read in from a database, the Internet, or some other dynamic data source, rather than populated by some sort of enum with display values coming from static strings that can be internationalized ahead of time.
This is not to say that your code is useless: if you find it useful, then it was worth writing. And I am sure that there are apps out there that contain your targeted pattern (i.e., a Spinner backed by an enum or equivalent where the display values are known in advance and can be internationalized) who might find your solution useful as well. Every developer who writes enough code cooks up these sorts of helper classes and the like that help map an OS or framework model into something that better fits the developer's own mental model. So long as you are not perceiving any performance issues, it's all good.
Also, note that OnItemSelectedListener is an interface; implementing that interface on an existing class is not inheritance.
I believe the reason nobody answered you is :
What problem are you trying to solve ? Spinners existed prior to your well designed attempt.
Why reinvent them in exactly the same way they exist in Android ?
http://developer.android.com/guide/topics/ui/controls/spinner.html
It is a beautiful wheel indeed you designed, but still, it is just a wheel :)
UPDATE :
I think I begin to understand what you did. This is interesting. I'm not sure why you did not go to the pattern implemented by the ListPreference with its entries and entryvalues.
In fact, I'm not sure I understand why the Android team did not go that route either.
In any case, it is worth proposing your idea to the Android framework. It is after all open source.
I've been working on the 'Tip Calculator' app for Android and I have a couple of questions.
I'm supposed to (in the process of creating the GUI) use some EditTexts to allow the user to enter the bill amount and read the calculated total bill. In the version I have, there is no EditText anywhere in the Visual Layout Editor, only CheckText. Are these the same?
Whenever I try to edit the Java code for the app, as per the book I have, I keep getting the message:
Thus and such is never used
For example, with
private static final String BILL_TOTAL = "BILL_TOTAL';
or anything from the import Android list, other than the one referring to a bundle. I'm Not sure how to resolve this. I have some experience with C and C++, but Java is new to me.
The warning that tells you that a variable or method or import is not used can be ignored, especially if you just haven't gotten to using it yet. It's a warning and not an error, so your app should compile regardless.
I don't know what you're using to build your layout (eclipse? I use Intellij Idea), but to add an EditText, you can edit the layout file by hand. Add a line similar to:
<EditText android:id="#+id/myEditText android:width="FILL_PARENT" android:height="WRAP_CONTENT"/>
As a general rule, I like to edit these things by hand. Then, when something breaks or doesn't work as I expect it to, I have some grasp of what's in there, and so I can usually fix it. The value gained by learning how to create a layout by hand easily offsets the value of the time that you'll save.
Good luck.
I've got a hell of a lot of Log.i Log.d Log.e in my code for a recent app I've done. I'm about to publish this app and I don't really want people seeing it when they plug there phone into adb, but I do want it there for my own debugging.
I was wanting to extend android.util.log and just have a boolean switch in there so I could just turn off the log when I publish and turn it on when developing but this class is final, am I missing a trick?
I don't really want to go through my code an remove all, true if worst comes to worst I could do a ctrl+h global replace Log for //Log but that does suck as an answer.
I also realise that Log.d is stripped out at runtime but it is still ran (losing a little performance) so not running this would be an added bonus.
Yeah so basically I'm looking for a way to toggle my debug on and off programatically, this can also allow me later on to make it a preference or something if people want to view it or help out and send it on.
What do you guys implement for this?
Thanks
As Octavian points out inserting a logging constant would be the best way to do this. Writing a new class for this that calls the original logging methods if debugging is enabled is not a good idea.
Good practice:
if (C.D) { Log.d(C.T, "your log text here " + foo + bar); }
Bad practice:
YourLog.d("your log text here " + foo + bar);
// and in YourLog.java's d() method:
... { if (debugging) Log.d(tag, text); }
The first solution is very fast if the constant D of class C is false. If you have complex string operations for creating your logging string they will not be executed if debugging is deactivated. The compiler can even remove these operations at compile time if D is false, which may result in zero runtime overhead. The second (bad) solution will always build the whole string and call a method, which is overhead you don't need.
In general the first solution would be best. And yes, I really call the class and members C, D and T (Constants/Debugging/Tag) - for performance reasons during typing. ;-)
obfuscate using Proguard as proguard has commands to use to filter it out when you write your proguard config file..nice and simple and it works
It is generally a good practice to not include them in your distribution code in any way since they will need to be processed which just leads to unnecessary battery drain.
You could set a boolean in your application somewhere to indicate development or release version of your code and have a lot of if blocks checking for the flag and executing your log code or not but this just leads to code bloat.
You should get rid of them once you no longer need them.