Tag: coding

  • Dao Error: Not sure how to handle query method’s return type //Android Kotlin Dev Diary

    As I brush up on my Room database knowlege I came upon the following error while building my app:

    WordDao.java:21: error: Not sure how to handle query method's return type (java.lang.Object). DELETE query methods must either return void or int (the number of deleted rows).

    The solution:

    Set Kotlin version to 1.6.10 then Room to 2.4.2 (Or use more recent compatible versions) in my top-level build.gradle file.

    Reference: Android Room Kotlin throws Delete Query error

  • Error: Type mismatch. Required: ActivityMainBinding. Found: ViewDataBinding! //Android Kotlin Dev Diary

    The problem is that this line of code is producing an error:

            binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
    

    And the error says:

    Type mismatch.
    Required:
    ActivityMainBinding
    Found:
    ViewDataBinding!

    The solution is to add a <layout> tag in the layout file that you are inflating!

  • Expand ScrollView vertically if height is smaller than screen // Android Dev Diary

    I have the following XML layout code in an Android app that I’ve been tinkering with:

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    
        <data>
            <variable
                name="viewModel"
                type="net.catzie.sampleapp.MainViewModel" />
        </data>
    
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <GridLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#aaa"
                android:columnCount="4"
                android:rowCount="5">
    
                ...
    
            </GridLayout>
        </ScrollView>
    </layout>

    I wrapped my GridLayout in a ScrollView because on the landscape orientation of the Android app’s screen, my grid contents are cut from the view because they’re too tall, and there’s no way to see them without a scrollbar, which the ScrollView provides.

    That gave birth to another problem though. The landscape view looks fine, but the vertical view became too short!

    After a few clicks at Google search results I found something that helped:

    android:fillViewport="true"

    I added the above attribute to my ScrollView, and voila! A GridLayout that scrolls vertically on landscape view, and fits the height of the Android device screen perfectly on portrait view~

  • Sample Instrumented Test for Retained Text After Screen Rotation // Android Kotlin Dev Diary

    First I added the following UI Automator to my app:

    androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'

    So now my build.gradle (Module) file has the following dependecies:

    dependencies {
    
        implementation 'androidx.core:core-ktx:1.7.0'
        implementation 'androidx.appcompat:appcompat:1.5.1'
        implementation 'com.google.android.material:material:1.6.1'
        implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
        implementation 'net.objecthunter:exp4j:0.4.8'
    
        testImplementation 'junit:junit:4.13.2'
        androidTestImplementation 'androidx.test.ext:junit:1.1.3'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
        androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
    
    }

    Then under the package app/src/androidTest/java/net/catzie/samplecalculatorapp I added the following instrumented test class:

    package net.catzie.samplecalculatorapp 
    
    import android.support.test.uiautomator.UiDevice
    import androidx.test.espresso.Espresso
    import androidx.test.espresso.ViewInteraction
    import androidx.test.espresso.action.ViewActions
    import androidx.test.espresso.matcher.ViewMatchers
    import androidx.test.ext.junit.rules.ActivityScenarioRule
    import androidx.test.ext.junit.runners.AndroidJUnit4
    import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
    import org.junit.Assert.*
    import org.junit.Rule
    import org.junit.Test
    import org.junit.runner.RunWith
    
    
    /**
     * Instrumented test, which will execute on an Android device.
     *
     * See [testing documentation](http://d.android.com/tools/testing).
     */
    
    @RunWith(AndroidJUnit4::class)
    class ValueRetainedInstrumentedTest {
    
        @get:Rule
        var activityRule: ActivityScenarioRule<MainActivity>
                = ActivityScenarioRule(MainActivity::class.java)
    
        @Test
        fun test_ui_value_after_screen_rotation() {
            Espresso.onView(ViewMatchers.withId(R.id.num_1)).perform(ViewActions.click())
            Espresso.onView(ViewMatchers.withId(R.id.num_period)).perform(ViewActions.click())
            Espresso.onView(ViewMatchers.withId(R.id.num_5)).perform(ViewActions.click())
    
            val device = UiDevice.getInstance(getInstrumentation())
            device.setOrientationLeft()
    
            val displayPanel: ViewInteraction = Espresso.onView(ViewMatchers.withId(R.id.display_panel))
            val displayPanelText = InstrumentedTestHelper.getText(displayPanel)
            assertEquals("1.5", displayPanelText)
        }
    }

    What it does is press the buttons 1, period, and 5 on the calculator’s UI to show “1.5” which should show up the display panel, rotate the screen of the emulator/device, and then check if the display panel is still showing the value “1.5”.

    I use a ViewModel and LiveData to let the value survive configuration changes such as screen rotation.

  • Prevent Huawei from Killing Your App //Android Dev Diary

    I have been playing around with Android app development, particularly on how to retain UI values after configuration changes and minimizing the app to launch a different one.

    To retain values after configuration changes, I use ViewModels.

    And to retain values after minimizing the app, the following is supposed to do the trick:

        override fun onSaveInstanceState(outState: Bundle) {
            super.onSaveInstanceState(outState)
             outState.putInt(KEY, number)
        }
        
        override fun onRestoreInstanceState(savedInstanceState: Bundle) {
            binding.textView.text = savedInstanceState.getInt(KEY)
        }
    

    But in the phone where I test most of my apps, it doesn’t! Minimizing my app to play a YouTube video, open a mobile game, and watch a few TikTok videos for about 15 minutes, causes my app’s UI data to reset.

    I installed the same app to another phone, a Samsung phone under the A Series. The user played a mobile game for several hours, and came back to my app to find all the previous UI values still intact!

    I remember that when I was still working with the Squadzip team (still grateful to Roman for suggesting that I try to practice “mindfulness” — it works wonders for a hectic lifestyle!), that Huawei phones gave us the same kind of issue. Apparently, Huawei phones are quite aggressive at killing apps in the background to preserve battery life.

    Options that I considered to prevent Huawei phone from killing my Android app in the background:

    • Save UI data to SharedPreferences, on top of using Bundle to save and restore instance state (hesitatant to do this because I don’t really need to save UI data)
    • Simply advise the user not to leave the app if they want their data to be retained (BAAAD IDEA!)
    • Find some sort of “whitelist” in Huawei settings to exempt my app from being aggressively killed

    The method I chose to prevent Huawei phone from killing my Android app:

    For the current app I’m working on, I chose to change a setting in the Huawei phone because it’s the easiest. It shouldn’t be so hard to explain to app users either.

    Instructions:

    • Go to Settings
    • Look for “Battery” and click on it
    • Look for “App launch” and click on it
    • Type the name of your app in the Search field.
    • Turn off the “Manage automatically” setting
    • Click OK on the prompt. (I chose to leave auto-launch, secondary launch, and run in background to keep my app alive.)
    • The description below your app’s name should now be “Manage manually” instead of “Manage automatically.”
  • DataBinderMapperImpl Error: cannot find symbol (DataBinding) //Android Kotlin Dev Diary

    Today I encountered the following error as I was building an Android app:

    DataBinderMapperImpl.java:18: error: cannot find symbol
    import net.catzie.myproject.databinding.ActivityMainBindingImpl;
    ^
    symbol: class ActivityMainBindingImpl
    location: package net.catzie.myproject.databinding

    Turns out, there’s an error in the related XML file, activity_main.xml! 😂

    For other possible solutions, this StackOverflower answer may help: android: data binding error: cannot find symbol class

  • Get “order” object/details from Thank You page of WooCommerce (WordPress)

    It’s been a long while since I last posted anything related to coding. I haven’t really stopped, but from Android app development, I switched back to PHP. Life has become occupied with other things, but when I do code, it’s in WordPress with WooCommerce. It’s for my online shop.

    In my opinion, WordPress is not the most pleasant platform to use if you’re a developer (after years of MVC coding for Android I find WordPress quite messy), but it’s what I already know. I don’t have time to learn another.

    Today’s code snippet is for customizing the Thank You page (post-checkout) by retrieving the “order” object.

    The $order_id is what we’ll start with. Then we get the order object with the help of the wc_get_order($order_id) method. Once you’re able to successfully call the order object, you may use its methods such as get_billing_first_name() to get the order details.

    You may refer to the WC_Order class page for a list of available methods.

    I originally got this code from Order Received (Thank you) page in WooCommerce and modified it to suit my needs. Check his blog out, as he has many helpful posts on how to customize WooCommerce!

  • Android app dev: Missing import org.apache.commons.lang3.text.WordUtils;


    I use a few instances of WordUtils.capitalizeFully() on an Android app that I’ve been working on. And there are times when the import org.apache.commons.lang3.text.WordUtils;
    breaks, sometimes after merging with some of my git branches.

    To fix this, what I do is open app/build.gradle and add the following line under dependencies:

    Hope this saves somebody else’s day 😆 I got the solution from How to add org.apache.commons.lang3 to AndroidStudio with gradle

  • Something to avoid when using Android RecyclerView

    When using Android’s RecyclerView, don’t use the same inflated XML layout file for items you intend to shuffle on the fly! Their contents will overlap.

    -CK

  • Setup/update Ruby on OS X El Capitan 10.11.5

    I need to learn Ruby on Rails for my new job. I’m a little thrilled about this chance to learn a new language, and I’m trying to get started with it on my Macbook which runs OS X El Capitan 10.11.5. I already have Ruby here, I don’t remember if pre-installed though. It’s out of date and I wanted to upgrade, as this resource Getting Started with Rails recommends version 2.2.2 or higher.

    First step I took was to get RVM (Ruby Version Manager):
    curl -sSL https://get.rvm.io | bash -s stable --ruby

    Then I received this message:

    ” * To start using RVM you need to run source /Users/catzie/.rvm/scripts/rvm
    in all your open shell windows, in rare cases you need to reopen all shell windows.”

    And so I ran:
    source /Users/catzie/.rvm/scripts/rvm

    Then:
    rvm install 2.4

    Which returned this message:

    Already installed ruby-2.4.0.
    To reinstall use:

    rvm reinstall ruby-2.4.0

    Finally, I ran this:
    rvm use 2.4 --default

    My next step was to install SQLite3 on my OS X as per instructions found here on SQLite – Installation.

    I got this message after following the instructions:

    SQLite version 3.17.0 2017-02-13 16:02:40
    Enter “.help” for usage hints.
    Connected to a transient in-memory database.
    Use “.open FILENAME” to reopen on a persistent database.
    sqlite>

    More on this in the future.

    Reference: Can I upgrade to the current version of Ruby (2.2.3) on OS X v10.6.8?