Alright so moving on now. We're going
to talk about onUpgrade, the function,
and also some testing. So the other
function we had to implement, if you
recall, to our, in our AppDatabase
class was onUpgrade. And if we take
a look at that, looking at the
documentation - let's scroll this up so
we can see it - it gets past the version
of the database that Android finds. So
the documentation explains that this
function's called when the database
needs to be upgraded.
Now when the function's called, it
gets passed the version of the database
that Android finds, and the current
version. So we passed the current version
number into the super method in the
constructor, so the SQLiteOpen
Helper class can track the versions for
us. Now we're obviously just starting
out so this is version 1, so there's
nothing to upgrade. We'll be adding some
more tables and views as we develop the
app, so I'm going to be discussing the on
Upgrade function in more detail when
we've actually got an upgrade to
perform. For now though what we're going
to do is, we're just going to of add some
dummy code and some logging. Alright so I'm
going to start with some logging, Log
.d parentheses TAG comma double quotes
onUpgrade colon starts. Alright, and
we're going to type when in parentheses,
old Version, and open a code block and
then we're going to type 1 dash greater than sign
and a code block. And I'm just going to put a
comment in there, "upgrade logic from
version 1". Then outside of that what we're
going to do is, do an else dash greater
than, and we're going do throw Illegal
StateException, in the parentheses, on
Upgrade parentheses in double quotes,
with unknown newVersion colon space, and
that's going to be $newVersion.
Alright. Now we can create a new instance
of our AppDdatabase class in Main
Activity's onCreate method, and request
a database connection to test that it
works. So let's go back to our MainActivity,
and specifically the onCreate method -
we're going to do just that. So I'm going
to start typing this code below the set
SupportActionBar - give it a space
there. So I'm going to start typing val
appDatabase equals AppDatabase dot
getInstance, then this in parenthesis.
Then we're going to type val db equals
appDatabase.readableDatabase. Then next
line, val cursor is equal to db.raw
query, and in parentheses I'm going to
type SELECT * FROM Tasks comma then
null - that's the second argument. Then I'm going to
do a Log.d parentheses TAG comma
and I'm just going to do a series of
asterisks there, and I'm gonna take
the opportunity now to add our tag at the
start of the file. So private const val TAG
equals MainActivity. Okay, and then below
the log entry we're going to do cursor
dot use. Open a code block, and then
we're going to type on the next line,
while parentheses it.moveToNext,
another code block. And a comment here
that were going to "Cycle through all
records", and then we're going to type with
parentheses cursor. Open yet another
code block and type val id equals get
Long zero in parentheses, and val name is
equal to getString, 1 in parentheses,
val description equals getString, 2 in
parentheses and then sortOrder, val sort
Order equals getString, 3 in parentheses.
And I'm going to type val result is
equal to, in double quotes, ID colon
space and $id full stop and name colon space
dollar name. Then I'm going to go space
there, then description colon dollar
description in sort order colon $ sort
Order. Then we're going to add another log
there, so Log.d parentheses TAG comma.
It's going to be onCreate reading data
$result, and then finally what I'm
going to do, is take a copy of this, these
Asterisks, and I'm going to add that
just above the fab.setOnClickListener there.
Alright so what's this code doing? Well
after getting an instance of AppDdatabase,
we run a query and log the task details.
This is very similar to the code we've
seen previously. We won't be performing
queries like this in the app though. This is
just a test that our AppDatabase class
is behaving as it should. Now I've added
a row of asterisks as you saw there,
before and after our data, because the
new logcat makes it harder to spot
our data. Alright, so now let's run our
application. So I'm going to click on the
button to start it, and I'm going to
open our logcat, just so we can take a
look and see what's happened. So firstly,
the getInstance function returns a new
instance of our singleton AppDatabase
class, and we can see the constructor
being called, here. We've got our App
Database initializing on the next line,
and then onCreate starting, and if you
recall onCreate - that function's called
for us because the android framework
detects that the database doesn't
already exist. So onCreate was called, as
we can see there, and there's our SQL
code. That's the code that creates the
database when that onCreate
function's called for us, because the
Android framework detected that the
database didn't already exist. So, so far
so good. This is really showing us what
we expected to be shown, or in other
words, the functionalities working as
expected. But what we want to do now is
check that the database really was
created, and does in fact contain our
Tasks table. So what we're going to do
now is close the logcat.
I'm going to open Terminal. We're going
to have a look at the database on the
emulator. So I'm going to start by typing adb
devices. Now most of the time when you do
that, you'll only have a single device
showing here. But I've got an emulator
and my one-plus Android phone connected,
and I've done it that way just so you
can see how to use adb shell when
there's more than one device available.
But you'll get an error if you try to
use adb commands with more than one
device connected to the computer, whether
they're emulators or physical devices.
Now the reason for the error is that adb
doesn't know which device you want to
use. If there's only one it doesn't have
a problem, but if you've got more than
one then you have to specify which
device you want to use. We do that with
the dash s switch. So my emulator is showing
up as emulator-5554, so the
command I need to type here is adb
space -s space emulator-5554
space shell. So basically you can see
that's connected now to the emulator, and
whenever you've got more than one device
connected just use -s and the device
ID
immediately after adb, and, which
specifies which device should be used.
Alright, so we're connected now to shell
on our emulator, so let's type su. We
need that super user mode, and that
probably won't work if you're using a
physical device, unless you've got root
access and you've also installed the su
command. So if you're testing this app on
a physical device, you'll probably have
to skip this step. But don't worry though,
were already confirming that the
database has been created. If it hadn't
been then we would have seen errors in
the logcat. Now we saw in an earlier
video that the databases
are created in the apps directory, in
/data/data in a database
directory. So make a note of your package
name, because that's also the name of the
apps home directory if you're using a
different package name to me. In my case
I'm going to type cd /data, that's
forward slash, /data again. That's
going to be learnprogramming.academy
dot tasktimer.
You can see that coming up automatically
when I clicked, when I pressed tab, and I'm
going to go into databases. Alright, so now
that I've done that I'm going to type
sqlite3 Tasktimer.db, and then
I'm going to type .schema, and
there's our Tasks table. Now remember
that Android is a Linux operating system
and the file and directory names are
case sensitive. So if your Task timer
database didn't open,
make sure you've used the correct case
for the name. Now this should be exactly
the same as the database underscore name
field in the AppDatabase class. Now while
we're here, I'm going to add some records
to the database. Now we're going to write
the code to display the tasks before the
code to add them, so these sample rows
will let us see that the display code's
working when we get to that point in
development. So I'm going to type
INSERT INTO Tasks parentheses Name comma
Description VALUES parentheses Task
Timer single quotes comma, single
quote for Tasktimer app creation, and
close off the single quote, right
parentheses and semicolon. Then next one,
we'll do INSERT INTO Tasks again,
parentheses, it's going to be Name
Description and SortOrder, separated by
commas, and another parentheses to close
it off - a right one - then VALUES
parentheses. We're going to go with
Android Java single quotes comma,
single quotes again, Android Java course
single quote comma, two right parentheses
and semicolon. Alright, the third I'm
going to type INSERT INTO Tasks
parentheses Name comma Description comma
and SortOrder comma right parentheses,
VALUES and parentheses again. This time I'm going
to type Android Kotlin and I'm going to type
Android Kotlin course - which of course
is this one - comma zero right parentheses
and
semicolon. Then we do a SELECT * FROM Tasks to
make sure that the records are there. We
can see the records are there. So at this
point our database is looking fine. So
we're going to quit sqlite by
typing .exit, then we're going to leave
super user mode by typing exit, without the
dot time. Then we're going to log
out of the Android shell by typing exit
once more. Then I can type exit one more time
and that closes the Terminal window. Al
right, so now there's some data in the
database. We should see it logged in the
logcat when we run the app again, so let's
go and try running that and see that it
works. We'll open logcat. Alright so
that's looking good. Our AppDatabase
class created the database, and is now
providing a database connection that we
can use. We've now got the Tasks Contract
and AppDatabase classes working. The
next step is to create the Content
Provider that we use to access the data
in the database, and we'll start work on
that in the next video.