IntroductionWelcome| 00:00 |
(music playing)
| | 00:04 |
My name is David Gassner, and this is
| | 00:06 |
Building a Note-Taking App for Android.
In this project course, I'll show you how
| | 00:12 |
to create a complete mobile app from
scratch using the Android SDK, and the
| | 00:15 |
Java Programming Language.
After installing Eclipse and the Android
| | 00:21 |
Developer Tools, and creating a starting
project, I'll show you how to save data to
| | 00:26 |
a device's persistent storage with the
shared preferences API.
| | 00:32 |
I'll then show to create the app's two
screen layouts, and create the Java
| | 00:35 |
classes that control them.
I'll create action bars and icons that
| | 00:41 |
control navigation, and show how to make
the app work well on multiple versions of
| | 00:47 |
Android.
This is one of three courses that describe
| | 00:51 |
how to build a note taking app for mobile devices.
| | 00:54 |
The others are for iOS and Windows Phone 8.
| | 00:58 |
I hope this course gives you the
information you need to start building
| | 01:01 |
your app for Android.
| | 01:03 |
| | Collapse this transcript |
| What you should know before watching this course| 00:01 |
This course is designed for software
developers who want to learn quickly how
| | 00:05 |
to build apps for Android mobile devices.
If you have experience building apps for
| | 00:10 |
other mobile environments, such as iOS,
Windows Phone, Blackberry or others,
| | 00:15 |
you'll find that there are a lot of
concepts that Android has in common with
| | 00:19 |
those SDKs.
But Android also has its own unique
| | 00:25 |
vocabulary and application architecture.
Here's some of the skills that you might
| | 00:30 |
find helpful in learning how to build
Android Apps.
| | 00:33 |
You'll be programming in Java, which is a
completely object-oriented programming
| | 00:38 |
language.
So, the more you know about
| | 00:41 |
object-oriented concepts such as
inheritance, encapsulation, and
| | 00:45 |
polymorphism, the more quickly this
application architecture will make sense.
| | 00:51 |
If you don't already know Java, it's good
to know at least one other programming
| | 00:54 |
language.
So, you can compare Java to what you
| | 00:57 |
already know.
And the most helpful of these languages
| | 01:01 |
would be C-style languages, such as C, C#
or JavaScript, because they have a lot in
| | 01:06 |
common with Java in terms of their syntax.
To get started with Java, you can watch
| | 01:14 |
the course, Java Essential Training.
In this course, I teach the basic syntax
| | 01:19 |
of the Java programming language.
How to install and use the Eclipse
| | 01:24 |
development environment.
And how to create project packages and
| | 01:28 |
classes for command line Java applications.
| | 01:32 |
You can also watch the Foundations of
Programming series.
| | 01:37 |
Most importantly, the fundamentals course
and the object oriented design course.
| | 01:42 |
So, you can learn move about OOP concepts,
and how they might be implemented in the
| | 01:47 |
Android environment.
To learn moree about Android, you can
| | 01:51 |
watch the course Android App Development
with Java Essential Training.
| | 01:57 |
In this course, you'll learn about the
basic application architecture of Android,
| | 02:02 |
including the relationship between
activities and screen layouts, and how to
| | 02:05 |
use graphics and animations.
And you'll get a complete tutorial on the
| | 02:11 |
Android Developer Tools, the Eclipse
plug-in that I use throughout this course.
| | 02:16 |
So, these are the skills that can help you
get started more quickly.
| | 02:20 |
But I'll show you everything you need to
know throughout this course.
| | 02:25 |
Because I'm going to show you how to code
the app from scratch.
| | 02:28 |
And you can use these other courses to go
back and understand more about what you've
| | 02:32 |
been programming.
| | 02:34 |
| | Collapse this transcript |
| Related courses| 00:00 |
This course, building a note-taking app
for Android, is one of three courses that
| | 00:05 |
are being released simultaneously in the
lynda.com library.
| | 00:10 |
The other two courses teach how to build
the same sort of note-taking app for other
| | 00:14 |
mobile platforms.
One of them focuses on iOS, the operating
| | 00:19 |
system that drives the iPhone, iPad and
iPod touch.
| | 00:23 |
The other course shows you how to build a
note taking app for Windows Phone 8 and
| | 00:28 |
specifically for Windows Phone 8, and as a
Windows Store App.
| | 00:33 |
The sort of app you would deploy on
Windows 8 and Windows RT.
| | 00:38 |
The goal of these three courses is to show
you how to use the native tools for each
| | 00:42 |
platform.
For Android, you'll be programming in
| | 00:46 |
Java.
For IOS in Objective-C, and for the
| | 00:49 |
Windows platforms, XAML and C#.
And the development tools are different
| | 00:55 |
too.
In this course, I'll be showing you how to
| | 00:59 |
work with Eclipse, with the Android
Developer Tools, or ADT plugin.
| | 01:04 |
For IOS applications, you build in Xcode.
And for Windows phone and Windows store,
| | 01:11 |
you'll use Visual Studio.
All of these programming languages and
| | 01:16 |
tools have rich capabilities for their
particular platforms.
| | 01:20 |
If you decide you want to build native
apps for each platform, these are the best
| | 01:24 |
available programming languages and tools
completely supported by the platform
| | 01:28 |
vendors.
| | 01:30 |
| | Collapse this transcript |
| Using the exercise files| 00:01 |
This course is accompanied by exercise
files that you can use to follow along.
| | 00:05 |
I've placed the exercise files on my
desktop, but you can copy them anywhere on
| | 00:09 |
your hard disk.
The exercise files include one folder for
| | 00:14 |
each of the course's chapters.
And within the folder, you'll find zip
| | 00:19 |
files.
Each of the zip files is an Eclipse
| | 00:22 |
archive project that you can import into
Eclipse when you're using the Android
| | 00:27 |
developer tools.
For example, the O3 getting started folder
| | 00:32 |
has a zip file called launcher icon.
And, if I go back a level.
| | 00:37 |
And then go the chapter, Data Model.
I'll find four ZIP files, for each of the
| | 00:42 |
four exercises in that chapter.
To use one of the exercise files, go to
| | 00:46 |
Eclipse with the Android Developer Tools,
and I'll describe how to install that
| | 00:51 |
early in the course.
From the menu, File > Import.
| | 00:57 |
In the Import dialog, go to the General
category, select Existing Projects Into
| | 01:04 |
Workspace and click Next.
Now, click on Select archive file.
| | 01:11 |
Click browse navigate to the Exercise
Files and go to the folder you want to
| | 01:16 |
work with.
I'll go to 04_DataModel.
| | 01:20 |
Then, choose the project archive file for
that exercise.
| | 01:26 |
So I'll open one called RetrievingData.
Then follow the rest of the prompts to
| | 01:32 |
complete the import process.
You should then be able to open up the
| | 01:37 |
project tree in the Package Explorer view,
and open the source folder in its Java
| | 01:42 |
classes, and the RES or resources folder,
and find all of the applications
| | 01:46 |
resources.
After importing any of the projects from
| | 01:52 |
the exercise files, if you see a series of
red warnings indicating that Java classes
| | 01:56 |
aren't being recognized, it typically
means that there's a problem with the Java
| | 02:00 |
compliance level.
It's a common issue when you have Java 7
| | 02:06 |
installed.
To fix it, go to the Project Properties to
| | 02:10 |
the Java compiler section.
And change your Java compliance level from
| | 02:17 |
1.7 to 1.6.
After saving the change, the errors should
| | 02:21 |
be cleared.
To run the application, click the Run
| | 02:25 |
button.
The first time you run a button after
| | 02:28 |
you've imported it, you'll see this
dialog, the Run As dialog.
| | 02:34 |
Choose Android Application.
If you have an Android device conected to
| | 02:38 |
your computer and you've enabled it for
USB debugging, you'll be able to load the
| | 02:42 |
application on the device and see it running.
| | 02:46 |
Or you can use the Android Emulator.
I'll describe how to use the emulator
| | 02:52 |
throughout the course and show you how to
create a variety of virtual devices to
| | 02:56 |
reflect the different screen sizes, pixel
densities, and versions of the Android
| | 03:00 |
operating system.
Once you're done with an exercise, you can
| | 03:06 |
close a project by right-clicking on it in
the Package Explorer and selecting Close
| | 03:10 |
Project.
Or, you can remove the project from your
| | 03:14 |
workspace completely by right-clicking and
choosing Delete.
| | 03:19 |
If you don't want to Delete the project
contents, leave this checkbox unchecked.
| | 03:25 |
Click OK and the project goes away.
But it's still there on your hard disk,
| | 03:29 |
and you can re-import it later.
The course is designed so that you can
| | 03:34 |
work through all of the exercises from
beginning to end using a single Eclipse
| | 03:38 |
project.
Or if you prefer, you could open up each
| | 03:42 |
project for each individual exercise to
make sure you're at the right point.
| | 03:47 |
It's up to you.
The exercise files also include a
| | 03:52 |
solutions folder.
And you'll see the same set of chapters
| | 03:55 |
there.
But the zip files there are the solution
| | 03:58 |
projects, the finished version of each exercise.
| | 04:02 |
I've named these with the suffix of
_solution so that you can open them at the
| | 04:06 |
same time in Eclipse as the starting
project because you can't have two
| | 04:10 |
projects of the same name.
You can then compare the two bits of code.
| | 04:17 |
Finally, there's an assets folder.
The assets folder contains one subfolder
| | 04:22 |
called logo.
And there you'll find a graphic that I use
| | 04:26 |
as the application's launcher icon.
There are two versions.
| | 04:31 |
One with square corners, and one with
rounded corners.
| | 04:34 |
And I'll describe why those exist, later
in the course.
| | 04:39 |
So those are all the assets that you'll
find in the Exercise Files.
| | 04:42 |
The course is designed, so you can work
through and build the app yourself
| | 04:46 |
following along with each video.
There are no typing help files.
| | 04:52 |
You'll do all the coding yourself.
And at the end of the course, you'll have
| | 04:56 |
a complete working app.
The app has already been distributed
| | 05:00 |
through the Google Play store, and the
Android app store.
| | 05:04 |
So you can't take this version of the app
and deploy it yourself, but you can take
| | 05:08 |
the lessons you've learned and apply them
to your own Android apps.
| | 05:13 |
| | Collapse this transcript |
|
|
1. Project OverviewFeatures of the note-taking app| 00:00 |
Before we gets tarted building the app,
I'd like to talk about the specifications.
| | 00:05 |
The application's requirements.
The name of the app is Plain Ol' Notes.
| | 00:11 |
And there are three versions of the app
for three different operating systems.
| | 00:15 |
In this course I describe how to build the
Android version.
| | 00:20 |
But there are also versions available for
Windows Phone and for iOS.
| | 00:25 |
The application implements these common
features of note taking apps.
| | 00:30 |
Users can create and edit simple notes
that are purely text based.
| | 00:35 |
There isn't any support for storing
photographs or other rich media.
| | 00:40 |
There are two screens in the app.
And the application implements navigation
| | 00:44 |
between the two screens and data sharing
between them.
| | 00:49 |
The notes are saved persistently to the
mobile device's storage.
| | 00:54 |
And we're using a feature of the Android
SDK called shared preferences to store
| | 00:58 |
that data.
And finally the application will be easily
| | 01:02 |
discoverable.
That is it follows visual design patterns
| | 01:07 |
that are common to android apps.
And so the user should be able to easily
| | 01:11 |
figure out how to use the application.
The application has two screens.
| | 01:17 |
The list screen displays notes in a list.
Each note occurs on a single line item.
| | 01:24 |
And only one line of the note is displayed.
| | 01:27 |
The Editor screen is where you can add or
edit a note.
| | 01:31 |
You get to the editor screen either by
touching the Plus icon to create a new
| | 01:35 |
note Or by touching an existing note.
The command pattern at the top of the
| | 01:42 |
screen is called the action bar.
The action bar interface was introduced in
| | 01:48 |
Android 3, or Honeycomb.
And it looks like this.
| | 01:51 |
It starts with the app logo or launcher
icon on the left.
| | 01:57 |
Then the name of the app and then a series
of command buttons.
| | 02:00 |
In our application, there will be only one
command button on the list screen.
| | 02:06 |
The plus icon to create a new note.
In the editor's screen There won't be any
| | 02:10 |
explicit command buttons on the right.
But the launcher icon will transform into
| | 02:16 |
a back button so the user can easily go
back to the list screen.
| | 02:20 |
The application will work on all versions
of Android going all the way back to
| | 02:25 |
Froyo, or Android 2.2.
And the user interface will adapt
| | 02:30 |
automatically to both different versions
of the operating system, and to different
| | 02:35 |
screen sizes and pixel densities,
including phones, and tablets.
| | 02:40 |
Here's a picture of the app running on a
Froyo based phone device.
| | 02:44 |
On a phone running Jelly Bean or Android
4.2, and on a Nexus 7, also running Jelly
| | 02:50 |
Bean.
There are subtle differences in the user
| | 02:53 |
interface between each of the three
devices, that are driven by the operating
| | 02:57 |
systems capabilities, and the size of the screen.
| | 03:02 |
Here are the requirements and features of
the list screen.
| | 03:05 |
As I mentioned the user can create a new
note by touching the plus icon.
| | 03:11 |
On the larger screens, the tablets, the
plus icon is accompanied by the text
| | 03:15 |
create just to the right of the plus icon.
For longer notes where the text doesn't
| | 03:22 |
fit on the line, the list item will be
automatically truncated and ellipsis or
| | 03:25 |
three dots will be shown at the end.
And if a note has line feeds, that is if
| | 03:31 |
it has multiple lines, only the first line
will be displayed.
| | 03:35 |
And once again, ellipsis will be shown at
the end.
| | 03:38 |
Finally, each list item shows a graphic on
the right side of the line.
| | 03:45 |
I've selected a pencil graphic to indicate
to the user that they can edit a note by
| | 03:49 |
touching it, but you can select any kind
of graphic that you prefer.
| | 03:54 |
On the editor screen the data entry will
word wrap automatically where necessary
| | 03:59 |
and will accept explicit line feeds to
support multi line text.
| | 04:06 |
On newer versions of the operating system,
the user can stop editing and return to
| | 04:11 |
the list screen by touching the devices
software based back button, or the app
| | 04:15 |
launcher icon in the action bar.
On older versions of the operating system,
| | 04:21 |
the user can finish editing by pressing
the hardware back button, or a back button
| | 04:25 |
that's a part of the user interface.
It'll look like it's in the action bar.
| | 04:32 |
But that's actually a fake out.
The action bar is only availible starting
| | 04:36 |
with Honeycomb.
But you can fake the action bar interface
| | 04:40 |
by making changes to your screen layouts.
This is what the app looks like on a Jelly
| | 04:46 |
Bean based phone, and it's using a real
action bar, and this is what it looks like
| | 04:49 |
when it's working on Froyo.
With the fake action bar.
| | 04:54 |
In both cases, the list screen has the app
logo or launch icon, the name of the app,
| | 04:59 |
and a plus icon.
The appearance is a little bit different,
| | 05:04 |
but all of the functionality works exactly
the same.
| | 05:08 |
| | Collapse this transcript |
| Demoing the finished app| 00:00 |
The app that I'm describing how to build
in this course is named, Plain Ol' Notes.
| | 00:05 |
I'll show you how to build it from start
to finish, and provide a completed version
| | 00:09 |
of the code.
But if you'd simply like to load it onto
| | 00:13 |
an Android device, a phone or a tablet,
you can get it from one of two places.
| | 00:19 |
It's available in the Google Play store on
this page under Plain Ol' Notes, and it's
| | 00:23 |
also available on Amazon.com for Kindle
Fire users.
| | 00:28 |
Again, named Plain Ol' Notes.
It's free in both environments.
| | 00:34 |
If instead you'd like to run through the
application on an emulator, you can go to
| | 00:38 |
Eclipse and import the code from the
exercise files.
| | 00:42 |
In Eclipse go to the menu and select File
> Import > Existing projects into work
| | 00:48 |
space.
Browse to choose an archive file.
| | 00:53 |
Go to the 01 overview folder and choose plainolnotes.zip.
| | 01:01 |
There are two projects in this archive:
Plain Ol' Notes and action bar sherlock,
| | 01:06 |
an open source library that the
application depends on.
| | 01:12 |
I'll finish the import process, and that
imports both projects.
| | 01:18 |
When you're working on your code and
testing it, make sure you have both
| | 01:21 |
projects open.
The Problems view will show a set of
| | 01:24 |
warnings.
You can ignore those, they're produced by
| | 01:27 |
the action bar Sherlock library and don't
do your application any harm.
| | 01:32 |
To test the application, go to the source
folder and to the default package, and
| | 01:37 |
open up one of the classes.
Then run the application on an emulator or
| | 01:44 |
a device.
I'll run it on an emulator that's running
| | 01:49 |
Android 4.2.2, or Jelly Bean.
The application has a very simple UI,
| | 01:55 |
there's a plus icon on the Action bar and
when you click it, you go into an editing
| | 01:59 |
screen.
Here you can type any note.
| | 02:05 |
I'll type here's a note.
And then you can either click the device's
| | 02:08 |
Back button, or the launcher icon which
has turned into an Up button.
| | 02:14 |
When you return to the List screen, the
note is saved persistently.
| | 02:18 |
I'll click Plus again, and I'll add
another note.
| | 02:22 |
And this time I'll click the Back button.
To edit an existing note, click or touch
| | 02:29 |
it, and then you can make changes and
return to the List screen and the changes
| | 02:35 |
will be saved.
And to delete a note, touch and hold for a
| | 02:42 |
moment, and you'll get a context menu,
touch Delete, and the note is gone.
| | 02:47 |
If you exit the application by returning
to the home screen and then restart it,
| | 02:52 |
the notes will still be there because
they're being saved to persistent storage.
| | 02:58 |
So I'll go to my App list and I'll load
the application again, and there's my
| | 03:03 |
note.
So that's it, a very simple application
| | 03:06 |
that's designed to teach you the critical
parts of building a note application.
| | 03:12 |
Two activities, a single editing
environment and saving the data
| | 03:15 |
persistently on the device, so that it's
still available after an application
| | 03:20 |
restart or a device reset.
| | 03:23 |
| | Collapse this transcript |
| Setting up the developer tools| 00:00 |
To get started building Android apps,
you'll need to download the Android
| | 00:05 |
developer tools available from this web
page, at
| | 00:08 |
developer.android.com/tools/index.html.
When you click the link to download the
| | 00:15 |
Android SDK, you're taken to this page,
and you should see a link to download the
| | 00:18 |
SDK bundle for your operating system.
I'm working on Mac OS X, so, I see the
| | 00:24 |
link for ADT bundle for Mac.
The bundle includes both the SDK for the
| | 00:29 |
latest version of Android and a customized
version of Eclipse.
| | 00:34 |
In order to run Eclipse, you'll need a
Java 6 run time.
| | 00:39 |
You can get that from Oracle if you're
working on Windows, or if you're working
| | 00:43 |
on Mac, on a slightly older version, it
might already be on your system.
| | 00:47 |
But, when you try to start up Eclipse on
Mac, if you're prompted to install a Java
| | 00:51 |
6 run time, you might see a failure when
you try to download it from Apple.
| | 00:57 |
And that's because, as of the time of this
recording, Apple has discontinued making
| | 01:01 |
that available directly.
But you can download the Java 6 run time
| | 01:07 |
and developer tools from this link, atsupport.apple.com/kb/dl1572.
| | 01:15 |
That will take you to a link that tells
you about Java for OS X 2013-002 or a
| | 01:20 |
later release.
And you can click the download link, and
| | 01:25 |
follow the prompts to install the right
version of Java.
| | 01:29 |
After you've installed the Java runtime
and you've downloaded the apb bundle and
| | 01:34 |
extracted it, you can then run Eclipse by
going into the bundle, opening the Eclipse
| | 01:39 |
folder and double-clicking on Eclipse.
Now again, if at this point you have
| | 01:46 |
problems getting Eclipse started, it will
most likely be because you don't have the
| | 01:49 |
right version of Java on your machine.
And you'll have to go get it and install
| | 01:54 |
it.
The bundle is delivered with the SDK, or
| | 01:57 |
software developer kit for the latest
version of Android only.
| | 02:02 |
As of the date of this recording, that was
Android 4.2, Jelly Bean.
| | 02:07 |
But if you want to support other versions
of Android and you'll probably want to,
| | 02:11 |
then you'll want to download at least one
other SDK version.
| | 02:16 |
To do that, go to the menu and select
Window > Android SDK manager.
| | 02:23 |
The Android SDK manager window will show
you what is already installed.
| | 02:27 |
Now, I've already made some changes in my installation.
| | 02:31 |
But initially, you should have the Android
SDK tools, and the Android SDK platform
| | 02:36 |
tools installed.
And you should have the SDK platform for
| | 02:40 |
the latest version of Android.
You won't have documentation
| | 02:44 |
automatically, but that's okay, you can
get that from the web.
| | 02:47 |
And you won't have SDKs for older versions
of Android.
| | 02:51 |
I recommend that you install the SDK
platform for Android 2.3, that's
| | 02:56 |
Gingerbread and Android 2.2, that's Froyo.
You only need the SDK platform downloads,
| | 03:03 |
you don't need anything else.
And then, if you're working on Windows and
| | 03:08 |
you want to debug with an actual device as
opposed to the software emulator, you
| | 03:12 |
should also go down to the extras section
and download the Google USB driver.
| | 03:19 |
You only need to do this on Windows.
If you're working on a Mac, you'll see
| | 03:23 |
this message.
That this driver is not compatible with
| | 03:27 |
Mac.
And that's because Android devices connect
| | 03:29 |
pretty much automatically on a Mac computer.
| | 03:32 |
So, if you followed all these steps.
You've made sure you have the right
| | 03:36 |
version of Java on your computer.
You've downloaded and extracted the
| | 03:41 |
Android developer tools bundle.
You've fired up Eclipse.
| | 03:45 |
You've opened up the Android SDK Manager.
And you've added in other earlier versions
| | 03:49 |
of the SDK, and on Windows, the USB
Driver, then you're ready for your next
| | 03:53 |
step.
Setting up some virtual devices that you
| | 03:57 |
can use for testing on your development computer.
| | 04:00 |
And I'll show you how to do that in the
next video.
| | 04:03 |
| | Collapse this transcript |
| Creating virtual devices for testing| 00:00 |
One of the greatest challenges in building
Android apps is the sheer volume of
| | 00:04 |
Android devices and operating system
versions that are out there.
| | 00:08 |
Just taking into account different
versions of Android, you can see from this
| | 00:12 |
data on the Android developer website the
number of different versions and how
| | 00:16 |
they're distributed in the user population.
| | 00:20 |
The latest version Jelly Bean 4.2 only has
1.6% usage as of March 2013.
| | 00:29 |
While Gingerbread, a much older version,
has over 40%.
| | 00:33 |
In large part that's because Gingerbread
is the latest version of Android that runs
| | 00:37 |
well on single core processors.
The later versions, Honeycomb, Ice Cream
| | 00:43 |
Sandwich and Jellyean all run best on Dual
and Quad-Core processors such as the
| | 00:47 |
Quad-Core processor that's in the Nexxus 7.
| | 00:51 |
So as a developer, you need to test on a
variety of operating systems and that
| | 00:56 |
doesn't even take into account the sheer
number of devices out there.
| | 01:02 |
As of last year, there were over 4,000
distinct Android devices in the market.
| | 01:08 |
And it's impossible for you to have each
one of them in your shop.
| | 01:12 |
And so, to test your application, you'll
need to use the Android emulator and
| | 01:16 |
create a variety of virtual devices that
reflect the different types of screens.
| | 01:22 |
Pixel densities and operating system
versions that you want to test on.
| | 01:27 |
You can easily create virtual devices from
within Eclipse through a piece of software
| | 01:32 |
called the Android Virtual Device Manager.
You can open it by going to the Clips
| | 01:38 |
menu.
And selecting window and then selecting
| | 01:41 |
the virtual device manager.
To test my application, I've created 3
| | 01:46 |
virtual devices.
I have one, that's a phone size and that's
| | 01:51 |
for the oldest version of android, that
I'm going to support.
| | 01:56 |
Android 2.2 or Froyo and then I have two
virtual devices, running on the latest
| | 02:00 |
version Android, as of the time of this recording.
| | 02:05 |
One that looks like a phone, and one like
a tablet.
| | 02:08 |
In order to make sure my application
behaves on a broad range of Android
| | 02:12 |
devices, I'll use these virtual devices.
I'll also test on actual devices.
| | 02:19 |
For my testing I use a Nexus 4 and a Nexus
7 for the most recent version of Android,
| | 02:23 |
an older phone, a Motorola Droid 2 that's
running on Gingerbread 2.3, and an
| | 02:28 |
original Kindle Fire that's also running
on Gingerbread, although a modified
| | 02:32 |
version.
To create your own virtual devices, click
| | 02:38 |
New, and give your virtual device a name.
For example, if I wanted to create a new
| | 02:44 |
virtual device that was a phone running on
Gingerbread, I might call it 'Phone
| | 02:48 |
Gingerbread'.
You AVD names can't have any spaces in
| | 02:53 |
them, but otherwise you can name them descriptively.
| | 02:57 |
Then, pull down to the device list, and
you can either choose one of the four
| | 03:01 |
named templates that are listed here, or
one of the screen sizes that are listed
| | 03:04 |
below.
So, for example If I wanted to emulate a
| | 03:09 |
phone running on Gingerbread, I might
choose the Nexus S.
| | 03:15 |
That has a screen resolution of 480 by
800, and a pixel density of HDPI.
| | 03:21 |
Then I would select a target, and I would
choose Android 2.3.
| | 03:25 |
Only the SDKs that you've installed in
your copy of eclipse will show up on this
| | 03:29 |
list.
And if you don't see the operating system
| | 03:33 |
version you're looking for, back out of
this process, go back to the SDK Manager,
| | 03:37 |
and install the right SDK.
Then close down Eclipse, restart Eclipse,
| | 03:44 |
and come back to this screen, and your SDK
should show up.
| | 03:49 |
Next, set options for your virtual device.
You can indicate that you want a hardware
| | 03:54 |
keyboard available, and you can select a
skin with hardware controls.
| | 03:59 |
If the app you're working on is going to
use a camera, you can emulate that using
| | 04:04 |
either a front or a back camera, or both.
You can set memory options to reflect what
| | 04:10 |
your device might have, and you can also
set internal storage And in SD card.
| | 04:17 |
I typically set my SD card size at 64 megabytes.
| | 04:21 |
Even if you do use the SD card in your
app, you probably won't use a whole lot of
| | 04:24 |
storage space during your testing.
And the smaller the size, the faster your
| | 04:30 |
emulator will start up.
Finally, to speed up loading of the
| | 04:34 |
virtual device, after the first time it's
loaded, Turn your snapshot option on.
| | 04:40 |
The first time your virtual device loads,
it's going to be deadly slow no matter
| | 04:44 |
what you do.
And that's even with a very fast
| | 04:47 |
processor, and even a solid state drive,
it's just slow.
| | 04:52 |
But if you use the snapshot option, the
second time you start up that virtual
| | 04:55 |
device, it'll be a lot faster.
After you've selected all your options,
| | 05:01 |
click OK.
And your virtual device will have been
| | 05:04 |
created.
You can either start up your virtual
| | 05:06 |
device from here, by clicking the start button.
| | 05:10 |
Or you can wait 'til later, when you're
actually ready to test your application.
| | 05:15 |
And I'll show you how to select and start
up a virtual device from within Eclipse,
| | 05:19 |
when we get to a review of the finished
application.
| | 05:23 |
| | Collapse this transcript |
|
|
2. Understanding Android SpecificsIssues in cross-platform development| 00:00 |
This course, and it's related courses,
building a note taking app for Android,
| | 00:04 |
iOS and Windows Phone are designed for
developers who want to build a single app
| | 00:09 |
and then deploy it on multiple mobile
operating systems.
| | 00:14 |
And have decided that the most important
thing is to get the best possible
| | 00:18 |
performance, the broadest access to
features of the devices, and if possible,
| | 00:23 |
direct support from the vendor that
created the operating systems.
| | 00:29 |
If this describes you, then you might
decide to use native tools and languages
| | 00:33 |
for each of the operating systems.
That's not the only way to get the job
| | 00:39 |
done.
There are many other options available.
| | 00:43 |
For example, if you're accustomed to
building web sites and web pages, you
| | 00:47 |
might decide to work with the tools
PhoneGap or Sencha.
| | 00:52 |
Both of these libraries let you build an
app interface with web standard languages
| | 00:57 |
and then wrap those web pages to make them
look like native apps.
| | 01:02 |
The libraries that come with these tools
let you work with device features such as
| | 01:07 |
geolocation centers and others.
The purpose of these tools is to let you
| | 01:13 |
build a single app and then deploy them to
iOS, Android, Windows Phone, BlackBerry,
| | 01:17 |
and any other operating systems that are
supported by that tool.
| | 01:23 |
You can learn more about these tools at
these websites.
| | 01:26 |
There are a number of platforms that are
specifically targeted at building game
| | 01:30 |
apps for multiple platforms.
These include Adobe's Flash, partnered
| | 01:36 |
with AIR, Unity, GameSalad and others.
These platforms let you build rich
| | 01:42 |
graphical interfaces using a variety of
tools and then program with a particular
| | 01:46 |
language that's designed for that platform.
| | 01:51 |
For example, flash works with actionscript.
| | 01:54 |
Unity lets you program in Javascript and
GameSalad is unique in that it let's you
| | 01:59 |
build game apps while writing zero code.
You can learn about these tools, at these
| | 02:06 |
websites.
You can also choose a platform that let's
| | 02:10 |
you program with a specefic programming language.
| | 02:14 |
For example, Titanium, Mono for Android,
and Xamarin.iOS.
| | 02:20 |
These tools are all designed to let you
use a language other than the native
| | 02:23 |
language.
And then to take your application and
| | 02:27 |
deploy it, either to a single operating
system or multiple operating systems.
| | 02:32 |
Titanium lets you program in JavaScript
and then deploy an app to multiple
| | 02:36 |
operating systems.
While Mono and Xamarin.iOS are targeted at
| | 02:40 |
a single operating system and let you
program in C Sharp.
| | 02:46 |
These tools might work well for you.
The downside to watch out for is typically
| | 02:51 |
they won't give you the best performance
that's available on the devices or there
| | 02:55 |
might be other compromises.
If you decide to go down the road of
| | 03:00 |
working with native tools and languages,
here's the challenge, you'll need to learn
| | 03:05 |
and work with multiple programming languages.
| | 03:09 |
Java for Android, Objective C for IOS and
C sharp or Visual Basic for Windows
| | 03:14 |
phones.
You need to learn different vocabularies
| | 03:18 |
and design patterns and you use different
developer's tools.
| | 03:23 |
You'll find that you can reuse some
application assets, such as graphics or
| | 03:27 |
data files.
But for the most part, you'll have to
| | 03:31 |
rewrite code for each platform.
But the benefit of this approach is great.
| | 03:36 |
You'll get the best possible performance
available on that operating system.
| | 03:42 |
You'll get complete access to all device features.
| | 03:44 |
You'll get direct support from the
operating system vendors and perhaps most
| | 03:49 |
importantly, you'll get the cleanest
upgrade path that's available.
| | 03:54 |
So, that what you'll need to learn to work
with multiple programming languages, Java
| | 03:59 |
for Android, Objective C for iOS, access
to those features first.
| | 04:04 |
And you won't have to wait for the other
platforms to catch up.
| | 04:09 |
The choice is yours.
This course will show you how to build
| | 04:12 |
Android apps using the native tools, the
Java programming language and the Eclipse
| | 04:16 |
Development Environment.
| | 04:20 |
| | Collapse this transcript |
| Unique concepts for Android| 00:00 |
Here are some concepts, vocabulary and
other ideas about working in Android.
| | 00:05 |
First let's talk about the screens that go
into making up an Android app.
| | 00:10 |
Each screen is known as an activity and
it's represented by a Java class.
| | 00:17 |
When you want to create a new screen, you
create a new class, you extend a class
| | 00:21 |
code activity, and you add the class to
your application by editing the app
| | 00:25 |
manifest.
We'll talk about all the details of this
| | 00:31 |
process later on in the video.
The activity's presentation is determined
| | 00:36 |
by it's layout.
You can predefine a layout using an XML
| | 00:41 |
file or a group of XML files known as fragments.
| | 00:47 |
Or you can build the layout dynamically at
run time with Java code.
| | 00:52 |
And then when you want to switch from one
activity or one screen to the next, you
| | 00:55 |
create an object called an intent.
Just like activities, these are
| | 01:01 |
represented by Java classes.
Each screen has a lifecycle.
| | 01:08 |
When you launch a screen it goes into a
state called created, from there into a
| | 01:12 |
state called started, and then into
something called resumed.
| | 01:17 |
As you're shutting down a screen, it goes
into a phase called paused, then stopped
| | 01:22 |
and finally destroyed.
It doesn't go through all these phases
| | 01:27 |
every time.
In fact a string is only destroyed when
| | 01:30 |
you explicitly turn off the app or when
the device needs to reclaim memory.
| | 01:36 |
But along the way the android runtime will
try to just certain methods of your Java
| | 01:40 |
classes.
These are methods that are already
| | 01:44 |
implemented and have certain default behaviors.
| | 01:47 |
But you can override these methods and add
your own behaviors.
| | 01:52 |
When you launch your application, its main
activity is launched activity.
| | 01:57 |
And the method onCreate is called.
This is the method where you'll put a lot
| | 02:02 |
of your initialization code.
And I'll show you the types of code we'll
| | 02:06 |
use in later videos.
From the created phase it goes to the
| | 02:10 |
started phase.
And a method code onStart is called.
| | 02:15 |
And then a method code onResume.
And then going back in the other direction
| | 02:19 |
you'll see methods code onPause, onStop
and onDestroy.
| | 02:24 |
When an activity is in the paused phase,
it can immediately go back to the resumed
| | 02:28 |
phase and then you'll call the method
onResume again.
| | 02:33 |
And when it's in the stop phase, it can
restart and that results in calling two
| | 02:37 |
methods, onRestart and onStart.
I won't be using all of these methods in
| | 02:43 |
this course.
My focus will be on the onCreate method,
| | 02:46 |
but they're all available to you as the
developer to extend so that you can
| | 02:50 |
control your app's behavior.
Here's a very small example of an activity
| | 02:57 |
class.
The name of the class is main activity.
| | 03:01 |
And it extends a class called ListActivity.
| | 03:05 |
Some activities extend ListActivity if
they're going to display lists of data,
| | 03:09 |
and some activities will extend simply the
activity class.
| | 03:13 |
It all depends on what that activity is
going to do.
| | 03:18 |
And in this class, I've created an
override of the onCreate method.
| | 03:23 |
The first thing it does is to call the
super classes onCreate method, and then it
| | 03:26 |
has some conditional code.
Figuring out which version of Android it's
| | 03:31 |
running on and selecting a screen layout
to determine how the screen will look.
| | 03:38 |
There are another few lines of code toward
the bottom of my onCreate method, register
| | 03:42 |
for context menu and assignment of a
variable called datasource and a call to a
| | 03:45 |
custom method called refresh display.
This is actually the onCreate method of
| | 03:51 |
the finished Plain Ol' Notes application
on Android.
| | 03:57 |
So, if you work through all of the
exercises in this course, you'll be coding
| | 04:00 |
all of this yourself and you'll understand
what each line of code does.
| | 04:06 |
In android, there is no specific
difference between a phone and tablet.
| | 04:12 |
For example, in iOS when you build an app
you designate it as an iPhone app or an
| | 04:16 |
iPad or Universal app.
In Android this distinction doesn't exist,
| | 04:23 |
instead you look at devices based on the screens.
| | 04:28 |
And a particular screen is defined by its
resolution, that is the number of pixels
| | 04:33 |
it has in width versus the number of
pixels it has in height.
| | 04:37 |
But then those values are categorized by
the operating system as small, normal,
| | 04:42 |
large, and extra large screens.
It's also important to know that each
| | 04:48 |
device is represented by a screen density
defined as the number of pixels within a
| | 04:52 |
physical area of the screen.
We referred to this as the dpi or as dots
| | 04:58 |
per inch.
And it's particularly important when
| | 05:02 |
you're creating graphics for your application.
| | 05:06 |
All of your graphic files along with other
kinds of files such as XML files are
| | 05:10 |
stored as what are known resources.
When you create your graphics, you'll need
| | 05:16 |
to provide them in multiple sizes for the
different screen densities.
| | 05:22 |
There are four screen densities to match
the four standard screen sizes.
| | 05:27 |
Low, medium, high, and extra high.
And I'll talk about how to create graphics
| | 05:33 |
of different sizes using certain automated
tools that are available on the web and
| | 05:37 |
where to put them in your application.
It's up to the Android operating system to
| | 05:43 |
decide which versions of your graphics
it's going to use at run time.
| | 05:49 |
As you're running your app, the Android
operating system looks at the device,
| | 05:53 |
determines the screen size and the screen
density and chooses a set of graphics for
| | 05:58 |
you.
All you need to do is provide the
| | 06:01 |
graphics.
So, that's a look at some of the common
| | 06:04 |
terms that you'll encounter in Android app development.
| | 06:08 |
And a look at how Android decides what
assets to use on screens of different
| | 06:12 |
sizes and densities.
| | 06:14 |
| | Collapse this transcript |
| iOS and Windows Phone developers beware| 00:00 |
If you're coming to Android from other
mobile operating systems, such as iOS or
| | 00:04 |
Windows Phone.
There are some common challenges that
| | 00:08 |
Android developers encounter that are
worth knowing about.
| | 00:12 |
I'll categorize these as the following.
Android as an open source software
| | 00:17 |
product.
Java and the Dalvik Runtime as a managed
| | 00:21 |
code environment.
The existence of multiple ways to
| | 00:25 |
distribute apps, and device fragmentation.
That is the large number of different
| | 00:31 |
devices, operating system versions and so
on, that exist in the Android ecosystem.
| | 00:37 |
Let's start with a discussion of Android's
open source status.
| | 00:41 |
Android is an open source product.
When Google creates a new version of
| | 00:45 |
Android, it typically releases that
version to the large device vendors first,
| | 00:50 |
such as Samsung, HTC, and so on.
These vendors then modify Android for
| | 00:55 |
their own devices, and release the devices.
| | 00:59 |
And at the same time, Google might work
with one of the hardware vendors to create
| | 01:03 |
what they call a reference device.
A device that represents what they think
| | 01:08 |
is perfect to run this version of the
operating system.
| | 01:12 |
Those reference devices are released under
the brand name Nexus.
| | 01:16 |
Google controls the development of the
core version of Android, but then gives
| | 01:20 |
the software away.
In the early going for each version, it
| | 01:24 |
will only go to the device vendors, but
then eventually Google will release that
| | 01:27 |
version of Android to everybody.
As of the time of this recording, Android
| | 01:33 |
4.2 was the most recent version you could
find on various devices, but 4.1 was the
| | 01:37 |
most recent version that was available as
pure open source.
| | 01:44 |
The good news is that because it's open
source, you can create your own version of
| | 01:47 |
Android.
That's what Amazon has done.
| | 01:50 |
It took a version of Android, and then
customized it for release on the Kindle
| | 01:54 |
Fire.
When you use a Kindle Fire, that version
| | 01:58 |
of Android look somewhat like the pure
version, but there are a lot of
| | 02:01 |
differences implemented by Amazon.
And the same thing is done by Barnes and
| | 02:07 |
Noble, and even Samsung, a very
large-scale device vendor.
| | 02:11 |
The downside is that you can only depend
on the devices with the Nexus brand to
| | 02:16 |
have the pure version of Android.
Nearly all other devices will have their
| | 02:21 |
versions of Android modified by the
vendors, and this contributes to what we
| | 02:26 |
call the fragmentation of the Android marketplace.
| | 02:30 |
I'll talk more about fragmentation at the
end of this video, but the open source
| | 02:34 |
status of Android is one of the great
contributors to this issue.
| | 02:38 |
The second issue to be aware of is that
Java is a managed code environment.
| | 02:45 |
That means that the Java programming
language doesn't support explicit memory
| | 02:50 |
management, it has a garbage collector,
and you create one file per class, in
| | 02:54 |
contrast to say Objective C.
This means that Java development can feel
| | 03:01 |
greatly simplified to developers who are
coming from Objective C.
| | 03:06 |
But some of the control they had over the
device, say in the iOS operating system,
| | 03:10 |
may not be available in the world of Android.
| | 03:14 |
The downside of the manage code
environment is that if you compared apple
| | 03:18 |
and apples.
That is if you take devices of exactly the
| | 03:22 |
same capability, and you write exactly the
same sort of functional code in Objective
| | 03:27 |
C for iOS and in Java for Android.
You might see lesser performance on the
| | 03:33 |
Android device.
Now, the reality of that issue isn't that
| | 03:37 |
important.
The newest devices coming out for Android
| | 03:41 |
have quad core processors and plenty of
resources to run java applications.
| | 03:46 |
But, if you're used to having very fine
tune control over the hardware and the
| | 03:50 |
operating system in the world of iOS, you
might find that you have less of that sort
| | 03:54 |
of capability in the world of Android.
Other issues in the Java programming
| | 04:02 |
language to be aware of are first that
Java is statically typed.
| | 04:07 |
In order to coordinate different classes
and different objects, you need very well
| | 04:11 |
defined interfaces.
If you're coming to Java from a more
| | 04:14 |
dynamic language, you might find that you
have to be much more specific to get your
| | 04:19 |
Java code to compile.
Developers coming to Android from say
| | 04:24 |
Windows Phone who are accustomed to
working with C Sharp will find this a very
| | 04:28 |
comfortable transition.
That's in part because C# is inspired by
| | 04:33 |
Java.
It shares a lot of Java's syntax and a lot
| | 04:37 |
of its behavior.
Particularly in regard to memory
| | 04:41 |
management.
Another issue to be aware of in Java is
| | 04:44 |
that floating point arithmetic isn't
always accurate.
| | 04:47 |
2 plus 2 doesn't always equal 4.
If you're working on an application where
| | 04:52 |
you're doing floating point arithmatic and
you're getting weird results, take a look
| | 04:57 |
at a class called big decimals.
The big decimal class can be used to solve
| | 05:03 |
common issues, such as inaccurate math.
It takes integers and keeps them as
| | 05:08 |
integers.
And it takes a certain number of decimals
| | 05:11 |
after the point, and retains that
information in a way that what we call
| | 05:15 |
primitive variables in Java might not be
able to.
| | 05:19 |
If you're coming from a programming
language where 2 plus 2 always equals 4,
| | 05:23 |
then this might seem very odd, but it's a
common issue in Java, not just in Android.
| | 05:31 |
And also beware about multi-threading.
The world of Java is such that if you're
| | 05:36 |
doing a multi-threaded application and you
encounter a crash condition in one thread,
| | 05:40 |
the entire app will come down.
That's not always the case in other
| | 05:45 |
environments.
But it's true in Android and with Java.
| | 05:48 |
Once you've finished an application and
you're ready to distributed it, you'll
| | 05:53 |
find that the Android world is very
different from say iOS or Windows Phone.
| | 05:59 |
Users who have iPads or iPhones can only
get their apps from the Apple app store,
| | 06:03 |
and the same thing is true in the world of
Windows phone.
| | 06:08 |
But in the world of Android, there are
multiple market places or app stores.
| | 06:13 |
The default one for most users is the
Google Play store.
| | 06:17 |
Formerly known as the Android app store.
This is where you can get the apps that
| | 06:22 |
have been distributed through Google.
But you also have vendors that have
| | 06:27 |
created app stores for particular app classes.
| | 06:31 |
Amazon for the Kindle Fire and Barnes and
Noble for the Nook.
| | 06:35 |
Commercial app developers tend to
distribute their apps through all of these
| | 06:39 |
stores if at all possible.
To hit the broadest possible population of
| | 06:44 |
Android device users.
And in addition to these major market
| | 06:48 |
places, there are many smaller websites
and app stores available, and I've listed
| | 06:53 |
some of them here.
These represent a small fraction of the
| | 06:58 |
Android ecosystem, but many Android app
developers like to distribute their apps
| | 07:02 |
through these stores as well.
As an app developer, the more stores you
| | 07:07 |
distribute through, the larger the number
of users you'll reach.
| | 07:11 |
But that means that when you upgrade your
app, you'll need to redistribute the app
| | 07:15 |
through all these stores as well.
You don't need to distribute through all
| | 07:20 |
of the app stores, choose the ones that
make sense for you and stick with them.
| | 07:26 |
The App store capabilities vary in a
number of ways.
| | 07:29 |
In security features, the level of
curation, the size of the audience they
| | 07:33 |
can reach, and their capabilities.
For example, the Barnes and Noble Nook app
| | 07:40 |
store, just recently implemented in-app
purchases as of early 2013.
| | 07:46 |
A capability that's been part of the
Google Play store for quite awhile.
| | 07:49 |
Finally, the biggest problem that Android
developers have to deal with is
| | 07:53 |
fragmentation.
As of 2013, there have been more than
| | 07:57 |
4,000 different models of Android devices
that have been created and sold.
| | 08:05 |
Not all of these devices have broad distribution.
| | 08:09 |
In fact, only about 150 device models in
total make up about 80% of the market.
| | 08:16 |
But if you're trying to get to everybody,
you really have a challenge in how you
| | 08:19 |
test your app and make it compatible with
all of these platforms.
| | 08:24 |
In addition to device fragmentation,
there's the fragmentation of the operating
| | 08:28 |
system itself.
Just taking into account, the pure
| | 08:33 |
versions of Android released by Google.
There are about seven major versions out
| | 08:37 |
there, starting with Froyo and all the way
through the most recent version, Jelly
| | 08:42 |
Bean.
You can find out the current statistics
| | 08:47 |
for usage of different versions of Android
at this website, atdeveloper.android.com.
| | 08:52 |
But then as I mentioned earlier, there's
also the different versions of Android
| | 08:56 |
that have been customized by different
device vendors.
| | 09:00 |
Device makers such as Samsung are
increasingly creating their own services
| | 09:05 |
that compete directly with Google's.
Their own music stores, their own music
| | 09:10 |
layers and so on.
And as an app developer, it's important to
| | 09:15 |
know what your app will be sitting alongside.
| | 09:18 |
So, how do you deal with fragmentation.
Well, the obvious answer is to test your
| | 09:23 |
application on as many physical devices as
you possibility can.
| | 09:28 |
I have four different Android devices.
An original Kindle Fire, an older Motorola
| | 09:33 |
Droid 2, and the newer devices, the Nexus
4 and Nexus 7.
| | 09:38 |
But that's just a small, small fraction of
the devices that are out there.
| | 09:43 |
And so, use the Android simulator.
Create as many virtual devices as you feel
| | 09:48 |
you need to, and test your application in
as many different scenarios as you
| | 09:52 |
possibly can.
And then hope for the best.
| | 09:57 |
When you release your app through any of
the app market places such as Google Play,
| | 10:01 |
if you provide a website for support of
your app I guarantee you'll hear from
| | 10:05 |
users for whom your app doesn't work on
their particular device.
| | 10:11 |
So, that's a look at some of the issues
that are common for Android developers,
| | 10:15 |
and that you might encounter if you're
developing for the first time in Android.
| | 10:20 |
And you're coming from other operating
systems such as iOS and Windows phone.
| | 10:25 |
| | Collapse this transcript |
|
|
3. Getting StartedCreating the Eclipse project| 00:00 |
So, let's get started building the
application from scratch.
| | 00:04 |
If you still have the plain old Notes
project open in Eclipse, you can remove it
| | 00:07 |
from the Package Explorer, by
right-clicking on the project, and
| | 00:10 |
choosing Delete.
If you don't select the option to delete
| | 00:14 |
the project contents on disk, the actual
project will still be there in the
| | 00:18 |
background, but it just won't be shown in eclipse.
| | 00:23 |
So, I'll click OK and I'm starting from a
blank slate.
| | 00:27 |
Now, I'll create my starting project.
I'll go to the menu and choose File > New
| | 00:33 |
> Android Application Project.
The application name can be anything you
| | 00:39 |
want.
I'll create my application name as Plain
| | 00:42 |
Ol' Notes.
The application name can contain spaces
| | 00:46 |
and special characters as needed.
The project name however, shouldn't have
| | 00:50 |
any spaces or special characters.
And it must be unique within your Eclipse
| | 00:55 |
workspace.
I'll create this project as starting
| | 00:59 |
project.
The package name must be globally unique.
| | 01:04 |
To guarantee that, you should start the
package name with your domain in reverse
| | 01:08 |
domain notation.
I'm going to set my package name as
| | 01:14 |
com.davidgasner.plainoldnotes.
If you're following along in these
| | 01:19 |
exercises to learn how to build the app, I
recommend using this same package name.
| | 01:25 |
But when you're ready to submit your own
apps to the Google Play or Amazon App
| | 01:28 |
Store, Or any other Android app store, you
should make sure you're using your own
| | 01:32 |
globally unique name.
If you try to submit an app with a package
| | 01:38 |
that's already in use, it'll be rejected.
Next, set the minimum required SDK.
| | 01:45 |
Eventually, this application is going to
support everything from froyo, Android
| | 01:49 |
2.2.
All the way through the most recent
| | 01:52 |
versions of Android.
But to make the early development process
| | 01:57 |
a little bit easier I'm going to set my
minimum required SDK to API-13 or Android
| | 02:03 |
3.2.
In the very last part of the development
| | 02:07 |
process, I'll be making the application flexible.
| | 02:10 |
So that it can adapt to different versions
of Android.
| | 02:13 |
But while I'm building it's primary
functionality, I'll stick with the most
| | 02:17 |
recent versions.
I'll accept all the other defaults on this
| | 02:21 |
screen and click Next.
On this screen, I'll uncheck the option to
| | 02:25 |
Create the custom launcher icon.
That's the graphic that's shown on the
| | 02:30 |
Android Start Screen and on the Home
screen on the more recent versions of
| | 02:33 |
Android.
I have my own launcher graphic that I'll
| | 02:38 |
be adding to the application later.
So, for the moment, I'll accept the
| | 02:42 |
default launcher icon, which will be a
picture of the Android robot.
| | 02:46 |
I'll accept all of the other defaults on
this screen and click Next.
| | 02:52 |
I'll accept the default to create a main
link activity, and click Next again.
| | 02:58 |
And I'll also accept these defaults for
the activity name, the layout name and the
| | 03:03 |
navigation type.
And I'll click Finish to create my project
| | 03:08 |
and app.
When the application first opens in
| | 03:12 |
Eclipse, it shows the main activities layout.
| | 03:16 |
A layout is an XML file.
It's displayed here in Wizzy Wig design
| | 03:21 |
mode, but you can also click the tab at
the bottom to see the XML format.
| | 03:27 |
The root element of a layout file is a
layout tag.
| | 03:31 |
And there are a number of different
layouts that you can use.
| | 03:35 |
We're starting with something called a
relative layout.
| | 03:37 |
And in this app, we'll use a combination
of relative layouts and linear layouts.
| | 03:43 |
Within the layout, there's something
called a TextView.
| | 03:47 |
The Text View is displaying a string
that's identified by this id hello
| | 03:52 |
underscore world and this value and
application name are defined in the file
| | 03:57 |
called strings.xml.
You can find that file in this folder
| | 04:03 |
named values.
Which is under another folder called res,
| | 04:07 |
for resources.
I'll double click the strings.XML file,
| | 04:12 |
and show the hello world identifier is
here, and that it has a value of hello
| | 04:16 |
world.
There's also an identifier for the app
| | 04:22 |
name.
I set this value when I created the
| | 04:25 |
project, and here is how the value is declared.
| | 04:28 |
With plain old notes and the apostrophe
with a prefix of a backslash.
| | 04:35 |
That's how you escape special characters
in simple strings in Android.
| | 04:40 |
Backslash apostrophe, backslash N for line
feed, and so on.
| | 04:45 |
So, now let's try running the application.
To run the application reliably, you
| | 04:52 |
should always have a Java class open.
I'll go to my source folder, and then to
| | 04:57 |
the package
com.davidgassner.plainoldnotes, And I'll
| | 05:00 |
open the one and only Java class that was
created by my new project.
| | 05:06 |
I'll double click the tab for the Java
class to open it up to full screen.
| | 05:10 |
And show that there are two methods in the
Java class.
| | 05:13 |
The onCreate method is called automatically.
| | 05:17 |
As this activity or screen opens up on the
Android device.
| | 05:23 |
It's calling a method called set content
view, which is in turn, opening the layout
| | 05:28 |
file activity_main.
And that's that same activity main xml
| | 05:33 |
file we already looked at.
There's another method here called on
| | 05:37 |
create options menu, and we'll come back
to that later in the development process.
| | 05:42 |
With the Java class open, I'm ready to run
my application for the first time.
| | 05:48 |
I'll go to the menu and choose Run and
then Run.
| | 05:51 |
The first time you run a project, you'll
probably see this run as dialogue.
| | 05:58 |
Choose Android Application and then
Eclipse should open an emulator.
| | 06:04 |
Load the application and run it.
If this is the first time you've run this
| | 06:08 |
particular emulator it might take a few
minutes to open.
| | 06:12 |
And you might be asked to click on an icon
in the middle and drag it to the right.
| | 06:17 |
But then once the application has been
installed and opened you should see it
| | 06:20 |
running on screen.
I'm just going to drag the emulator to the
| | 06:24 |
center of the screen and then I'll come
back to ecliipse.
| | 06:28 |
And I'll make one little change.
I'll go to my strings.xml file and I'll
| | 06:33 |
change my hello world id from hello world
to hello from plain old notes.
| | 06:41 |
I'll save my changes by pressing Cmd+S on
Mac or Ctrl+S on Windows.
| | 06:49 |
Then I'll click back on the Java class
mainactivity.Java and this time I'll run
| | 06:54 |
by clicking the Run button on the toolbar.
After clicking the button, I'll switch
| | 07:00 |
back to the emulator and after a moment I
should see the new version of the
| | 07:04 |
application loaded and running in the emulator.
| | 07:09 |
So, that's how we get started building the
simple application.
| | 07:12 |
There's obviously a lot more work to do,
including changing the icon to a custom
| | 07:17 |
icon, but I'll describe how to do that in
the next video.
| | 07:22 |
| | Collapse this transcript |
| Creating a launcher icon| 00:00 |
When you first create an Android
application, it's populated by default
| | 00:04 |
with a launcher icon, a picture of the
Android robot.
| | 00:09 |
Or you can create your own custom icon
during the project creation process.
| | 00:13 |
But when you're building a commercial app,
you'll probably have a graphic designer
| | 00:17 |
create your own custom icon.
And you're going to need to create a
| | 00:22 |
number of different versions of it.
One for each of the common pixel densities
| | 00:26 |
or screen densities that you'll find on
different Android devices.
| | 00:30 |
The launcher icon is shown both in the
action bar when you're working on a newer
| | 00:35 |
version of Android.
And, after you've installed the
| | 00:39 |
application, it'll show up in the
application list and sometimes on the
| | 00:42 |
start screen.
You can add the application to the start
| | 00:46 |
screen by going to the application list,
clicking and holding on the application,
| | 00:51 |
and then dropping it on your start screen.
When you first create the object the
| | 00:58 |
application is populated with three
different sizes for the application
| | 01:02 |
launcher.
There's one in a folder called Drawable
| | 01:06 |
HDPI for high density devices.
One in MPDI for medium and in XHDPI for
| | 01:12 |
extra high density.
Your job is to take your original graphic
| | 01:17 |
design and create the various sizes that
are needed.
| | 01:22 |
Fortunately there's a tool that will make
this very easy.
| | 01:27 |
Here are the graphics that I'm going to be using.
| | 01:30 |
I'll minimize Eclipse and the Emulator and
then I'll go my exercise files.
| | 01:36 |
Within the exercise files there's an
assets folder and under that logo folder.
| | 01:43 |
I've provided two different versions of my
launcher icon design the first is an
| | 01:47 |
original graphic that might have come from
a graphic designer.
| | 01:52 |
It's a square.
Your launcher icon should be the same
| | 01:57 |
dimension in height and width.
And this original graphic is 1024 by 1024.
| | 02:03 |
But there's an important feature of
launcher icons that's required in the
| | 02:06 |
Android system.
Each launcher icon should implement at
| | 02:10 |
least some transparency or alpha channel
to give it a unique silhouette on the
| | 02:15 |
screen.
It doesn't have to be absolutely unique.
| | 02:20 |
But it shouldn't be a simple square.
And so, I've created and have provided a
| | 02:24 |
version of my graphic that has rounded corners.
| | 02:29 |
And the corners on the outsides are transparent.
| | 02:32 |
This is enough transparency to satisfy the
Android requirement.
| | 02:36 |
You can create this sort of png file in
fireworks, photoshop, illustrator, and
| | 02:41 |
many other graphic design applications.
For this exercise, I'm going to use this
| | 02:48 |
finished graphic.
The easiest way to create the different
| | 02:52 |
sizes that you need is with a free web
based application called the Android
| | 02:56 |
Assets Studio.
I'll go to my browser.
| | 03:01 |
And then to the Android Assets Studio,
which I've bookmarked.
| | 03:05 |
The Android assets studio is completely free.
| | 03:07 |
And it will help you create the different
size icons that you need for your
| | 03:11 |
application launcher, for Action Bar and
Menu icons and many others.
| | 03:18 |
I want to create a launcher icon.
So I'll click that link.
| | 03:21 |
And that takes me to the launcher icon generator.
| | 03:25 |
You can create Launcher icons using one of
these standard clip-art graphics.
| | 03:30 |
Or you can use text.
Or as I'm going to do here, you can use
| | 03:33 |
your own custom-designed image.
I'll click the Image tab and that opens up
| | 03:39 |
a browse dialogue.
Then, I'll navigate to the Logo folder
| | 03:43 |
under my Assets folder under Exercise files.
| | 03:46 |
And I'll choose the version of the graphic
that has the alpha or transparency.
| | 03:52 |
It takes just a moment to upload the file
to the Android Asset Studio screen.
| | 03:56 |
Now, I can do all sorts of things to
modify it.
| | 04:00 |
I can add padding, add transparent
foreground color, scale it with cropping,
| | 04:04 |
shapes and add backgrounds, but I'm going
to accept it But I'm going to accept it in
| | 04:09 |
its default setting.
Now, scroll down to the bottom.
| | 04:12 |
And now I see the different size graphics
that are going to be generated by the
| | 04:18 |
asset studio.
By default, I'll get four different
| | 04:21 |
graphics.
One for extra high density.
| | 04:24 |
One for high density.
And one for medium.
| | 04:27 |
But also one for extra extra high.
If you're going to be submitting your
| | 04:32 |
application to the Google Play or Android
apps stores.
| | 04:36 |
also generate a web icon, you'll need that
icon when you're ready to submit the app.
| | 04:42 |
To do that, just click the Generate Web
Icon button.
| | 04:45 |
And you'll get an extra large version of
the icon that's suitable for that purpose.
| | 04:52 |
Scroll back up to above the preview
display, and click Download Zip.
| | 04:57 |
That results in creating and downloading a
file called ic_launcher.zip.
| | 05:02 |
Now go to the folder where that was downloaded.
| | 05:05 |
It should appear in your Downloads folder.
Then, extract its contents.
| | 05:11 |
On Mac, you can just double click the zip file.
| | 05:14 |
On Windows, you'll have to write click,
and select Extract.
| | 05:19 |
Then, double click to open the folder that
was created.
| | 05:22 |
And you'll find the 512 by 512 version,
plus a folder called RES.
| | 05:28 |
This RES folder for our resources, matches
the RES folder in your project's directory
| | 05:33 |
structure.
And just as with your project, it contains
| | 05:38 |
name folders for each of the different
graphic sizes.
| | 05:41 |
To take these files and add them to your
project go back to the folder that
| | 05:46 |
contains the RES folder.
Select everything and copy it to the
| | 05:52 |
clipboard.
I press Cmd+C on Mac, you can press Ctrl+C
| | 05:56 |
on Windows.
Then come back to Eclipse.
| | 06:01 |
Go to your project folder, right click and
choose Paste.
| | 06:05 |
When prompted to overwrite select Yes To All.
| | 06:09 |
That will result in overwriting the
default PNG files and where necessary
| | 06:14 |
creating new folders.
You'll have the four different size
| | 06:18 |
launchers that you created.
And you'll have the web version as a
| | 06:22 |
member of the project root.
Then go back and take a look at your
| | 06:26 |
layout and you should see the new icon is
displayed in the action bar.
| | 06:31 |
Run the application again in the emulator,
and you should see the custom icon appear
| | 06:35 |
next to the application name.
And if you go back to the home screen or
| | 06:39 |
to the application list, you should see
the custom icon appear there too.
| | 06:45 |
So, that's how we take a basic graphic and
turn it into a launcher icon with all the
| | 06:49 |
different sizes you need to display on
different Android devices.
| | 06:54 |
And also the larger web version that
you'll use when you submit the app to an
| | 06:58 |
app store.
| | 07:00 |
| | Collapse this transcript |
|
|
4. Creating the Data ModelUsing local data storage| 00:00 |
The Android SDK offers multiple Options
for storing and retrieving data
| | 00:04 |
persistently on Android devices.
The Options include: shared preferences;
| | 00:11 |
arbitrary files in the format of your
choice, including XML or JSON, and SQLite
| | 00:16 |
based relational databases.
All three of these options let you persist
| | 00:23 |
data.
That is, save the data to device data so
| | 00:27 |
that it sticks around between application
launches, or between the time you shutdown
| | 00:32 |
a device and start it up again.
The shared preferences API is the simplest
| | 00:38 |
of these options.
A shared preference is simply a data
| | 00:43 |
object, and the form is a key value pair.
The key is always a string, but the value
| | 00:50 |
can be one of a number of data types,
including integers, long integers,
| | 00:54 |
doubles, Booleans, and strings.
You can manage shared preferences data,
| | 01:00 |
either completely programatically using
Java, or through a special kind of
| | 01:05 |
activity or screen called a preference activity.
| | 01:11 |
In this course, I'll only be working with
shared preferences using the Java
| | 01:14 |
programming language.
You work with shared preferences using the
| | 01:19 |
API, but the data is actually stored in an
XML file that's saved on disk.
| | 01:25 |
You don't have to use any XML parsing
libraries, such as DOM, or SAX, or JDOM,
| | 01:29 |
that's all done for you by the preferences API.
| | 01:33 |
And it is important to note that shared
preferences are stored unencrypted.
| | 01:40 |
That is in plain text.
That doesn't mean it's easy for users to
| | 01:44 |
see the data, to get access to shared
preferences XML files they have to root
| | 01:49 |
the device.
That is, get complete administrative
| | 01:53 |
access to it.
But it's not encrypted, and if you need
| | 01:56 |
encryption then shared preferences is
probably not the way to do it.
| | 02:01 |
The Android SDK also has support for
creating your own files in what ever
| | 02:05 |
format makes sense for your application.
These files can be created and read on
| | 02:13 |
persistent media, and they can be read and
written with standard Java file APIs.
| | 02:19 |
There's not particular format for these files.
| | 02:21 |
You can choose XML or JSON, or delimited
data files, or binary files.
| | 02:27 |
Again, whatever makes sense for you.
And it's possible to create read-only
| | 02:31 |
files that you can toss into an
applications resources folder and then
| | 02:35 |
address through a resource ID.
Just like you might with a layout file, a
| | 02:41 |
drawable graphic file or other resources.
And files can be created in either
| | 02:47 |
internal storage.
That is, where it's local to the
| | 02:50 |
application, or external locations, where
the files can be shared with other
| | 02:54 |
applications.
Finally there's SQLite.
| | 02:59 |
SQLite is a powerful database engine.
And the Android SDK has its own API for
| | 03:06 |
working with SQLite databases on Android devices.
| | 03:10 |
SQL lite is great where you need to work
with highly structured data with multiple
| | 03:15 |
tables that are joined together, and you
want to work with the SQL language.
| | 03:21 |
Android has its own implementation.
And you can find a lot more information
| | 03:28 |
about SQLite at www.sqlite.org.
But, you should look at the documentation
| | 03:33 |
that comes with android to find out how to
work with it in this environment.
| | 03:38 |
This includes all of the classes and
interfaces that are in the
| | 03:42 |
android.database.sqlite package.
So, those are all the options that are
| | 03:47 |
available for working on Android.
In this course, the data we'll be saving
| | 03:52 |
is notes.
And each note is a key/value pair where
| | 03:56 |
both the key and the value are strings.
The key will be a unique date-time stamp
| | 04:02 |
expressed as a string, and the value will
be any Java-based string.
| | 04:08 |
The shared preferences API is perfect for this.
| | 04:11 |
It makes it very easy to store key/value pairs.
| | 04:15 |
And using a little bit of Java wizardry,
we can easily sort the data by the keys.
| | 04:21 |
If you want to learn about other options
for working with data on Android devices,
| | 04:25 |
watch the Lynda.com course, Android SDK:
Local Data Storage.
| | 04:30 |
But in this course, I'll show you
everything you need to know about shared
| | 04:34 |
preferences for building this particular
note taking app.
| | 04:38 |
| | Collapse this transcript |
| Modeling a data item with a Java class| 00:00 |
Regardless of how you're going to store
data in your Android app the first step in
| | 00:04 |
creating a data persistence layer is to
create a Java class that models the data
| | 00:08 |
you're going to store.
I'm going to be storing notes and each
| | 00:14 |
note is going to have a key and a value.
So, I'm going to create a Java class that
| | 00:19 |
has those two properties or fields.
I'm working in a version of my project
| | 00:24 |
called data item.
And I'll go to the source folder within
| | 00:28 |
the data item project.
Right now, my project only has a single
| | 00:33 |
package, the application package.
I'm going to create a subpackage.
| | 00:39 |
And I'm going to put all the Java classes
that have to do with data management in
| | 00:43 |
that package.
I'll right-click on the existing package
| | 00:48 |
and choose new package and I'll add a sub
package of .data and click Finish.
| | 00:55 |
Now I'm ready to create my Java class.
I'll right-click on the package and I'll
| | 01:02 |
select new class and I'll name the new
class note item.
| | 01:09 |
You can name this class anything you want,
and you'll see a variety of different
| | 01:12 |
naming conventions.
You'll see some developers use a suffix of
| | 01:18 |
DTO, for Data Transfer Object, or VO, for
Value Object.
| | 01:24 |
I typically use item to indicate that this
is an item of data.
| | 01:28 |
The superclass is Java.lang.object.
That is we're not extending or inheriting
| | 01:35 |
from any particular Java class.
This is the kind of class sometimes known
| | 01:40 |
as a POJO or a Plain Old Java Object.
It'll have whatever properties we define
| | 01:47 |
and whatever methods we define, but
nothing else of significance.
| | 01:52 |
I'll click Finish and that creates my new
Java class.
| | 01:56 |
Next, I'm going to declare the two
properties that my object is going to have
| | 02:00 |
the key and the text value.
I'll place the cursor inside the class
| | 02:06 |
definition, and I'll declare two private fields.
| | 02:10 |
I'll start with private string, and then
the name of the field, key.
| | 02:16 |
And I'll declare a second field, also a
string, and I'll set this ones name as
| | 02:21 |
text.
Whenever you create private fields within
| | 02:25 |
a class you need to make them publicly
accessible to the rest of the application.
| | 02:31 |
And you do that using getter and setter methods.
| | 02:34 |
Eclipse is able to generate that code for you.
| | 02:38 |
So, I'm going to select these two private
fields then I'll right click and I'll
| | 02:43 |
choose Source, Generate Getters and Setters.
| | 02:49 |
I see the two fields in the class that I
just defined, and I'll click Select All.
| | 02:53 |
I'll set the insertion point for After
Text, and then I'll click OK.
| | 03:00 |
And that generates a getter and a setter
for each of the two private fields.
| | 03:05 |
These values will now be available to
anywhere else in the application.
| | 03:10 |
Finally, I'm going to add some custom
code, to this particular class.
| | 03:15 |
Whenever we create a new node in the
application, we're going to automatically
| | 03:19 |
set the key, using the date, time stamp
for the current time, on the android
| | 03:23 |
device.
So, instead of using a standard
| | 03:28 |
constructor method, that is a method where
you say, create a new note with new note.
| | 03:35 |
Instead, we're going to create a special
method called get new.
| | 03:39 |
I'll be adding more code here, so I'm
going to go into full screen mode by
| | 03:43 |
double-clicking on the tab at the top of
the editor.
| | 03:47 |
Then, I'll place the cursor after my
getters and setters and I'm going to
| | 03:50 |
create a new public method.
It's going to be static which means that
| | 03:54 |
this method can be called from the class
without first instantiating the class.
| | 03:59 |
I'll start with public then static, and
then the name of the class, note item, and
| | 04:03 |
the name of the method, get new.
Placing the name of the class before the
| | 04:09 |
name of the method means that we're going
to be returning an instance of that class
| | 04:14 |
from this method within the method here
are the steps we have to follow.
| | 04:22 |
First, we have to set the key value and
that's going to be drawn from the date
| | 04:27 |
time stamp that is the current time of the
current device down to the second.
| | 04:34 |
Here is the code we'll use.
I'll start by declaring an instance of a
| | 04:39 |
class called locale.
I'll type in the name of the class, then
| | 04:43 |
I'll press Ctrl+Space.
And I'll select locale from the list of
| | 04:48 |
available classes.
That results in adding an import statement
| | 04:52 |
to the top of the class, and it will allow
me to use that class throughout all the
| | 04:55 |
code in this class.
I'll go back to the code I'm creating and
| | 05:01 |
I'll name the object that I'm creating
locale also but, with a lower case initial
| | 05:05 |
character.
In Java Conventions, the upper case
| | 05:10 |
initial character means it's a class and
the lower case means it's an object or an
| | 05:14 |
instance of a class.
Next, I'll instantiate the locale with
| | 05:20 |
equals new.
And then, I'll use the locale classes
| | 05:25 |
constructor method and I'll pass in a
string of en_US.
| | 05:32 |
Even if you're not working in the United
States, and even if you're going to be
| | 05:35 |
translating your application, I strongly
recommend using this locale.
| | 05:41 |
For the task we're about to follow, which
is getting the current date time stamp.
| | 05:46 |
The English US locale will give you a
date/time stamp that's easily sortable.
| | 05:50 |
And that's going to be an important
feature of our application.
| | 05:53 |
Sorting the data by when it was created.
Next, we'll call a method called set
| | 05:59 |
locale.
And this is a static method of the locale
| | 06:03 |
class.
So, I'll type Locale.setDefault, and I'll
| | 06:07 |
pass in my locale object.
The locale object's name was suggested by
| | 06:13 |
Eclipse.
And then, I pressed Tab to get to the end
| | 06:17 |
of the line, and typed in the semicolon to
finish the statement.
| | 06:22 |
Now, I'm ready to use that locale to
create a date time stamp.
| | 06:27 |
To create the date time stamp, I'm going
to be using another Java class called a
| | 06:31 |
simple date format.
The simple date format class takes a
| | 06:35 |
string pattern that indicates the format
of the date time I want to get.
| | 06:42 |
To define that, I'll declare a variable as
a string that I'll name pattern.
| | 06:47 |
And I'll use this string, yyyy in lower
case then a dash, then two Ms in upper
| | 06:54 |
case.
Then another dash and two d's in
| | 06:59 |
lowercase.
This will give me the year in a four-digit
| | 07:02 |
format, the month in a two-digit numeric.
And the current day of the month in a
| | 07:07 |
two-digit numeric, and separated by hyphens.
| | 07:11 |
Then I'll put in a space, and here's the time.
| | 07:15 |
HH in upper case, mm in lower case and ss
in lower case.
| | 07:22 |
This time separated by colons.
And finally at the end, Z.
| | 07:30 |
The Z means add notation that shows the
offset from Greenwich mean time.
| | 07:35 |
So, now I'll have a completely unique date
time stamp that's generated from the
| | 07:39 |
current Android device.
And the format will be sortable based on
| | 07:44 |
when it was created.
Now, I'll create an instance of the simple
| | 07:48 |
date format class.
I'll type the beginning of the class name,
| | 07:53 |
simple d and press Ctrl+Space.
And that automatically auto completes the
| | 07:59 |
name of the class and adds an import
statement for the class at the top of the
| | 08:02 |
code.
Going back down to where I'm coding, I'll
| | 08:07 |
name this object formatter.
And I'll instantiate it using a
| | 08:13 |
constructor method of this class.
Call a new simple date format.
| | 08:19 |
Once again, I'll type in the beginning of
the class name and press Ctrl+Space.
| | 08:24 |
And then, I'll choose the version of the
constructor method that I want to use.
| | 08:28 |
A version where I pass in a string pattern.
| | 08:31 |
I'll select that constructor method.
I'll press Tab and finish the statement.
| | 08:37 |
Finally, I'll create the key value by
calling the formatter objects format
| | 08:42 |
method, and I'll pass in the current date
time value.
| | 08:46 |
That code looks like this.
I'll create a string variable named key.
| | 08:51 |
And I'll get its value from
formatter.format, and I'll pass in a new
| | 08:55 |
instance of the date class.
I'll press Ctrl+Space, and select a
| | 09:00 |
constructor method for that class.
That adds an import statement where
| | 09:05 |
necessary, and I'll Tab and complete the statement.
| | 09:09 |
And now, I have a string value that will
be used for the key of the current note.
| | 09:14 |
So, now I have a key and I'm ready to
create the node object.
| | 09:19 |
I'll declare a new variable as a NoteItem,
and I'll call it note.
| | 09:23 |
And I'll instantiate using the default no
arguments constructor method of this
| | 09:28 |
class.
That code looks like this, new NoteItem.
| | 09:33 |
In Java, if you don't define an explicit
constructor method, the class will be
| | 09:39 |
given an automatic null arguments
constructor method.
| | 09:44 |
If you prefer you can define it explicitly
but at this point its not needed.
| | 09:49 |
Now, I'll set the note objects key using
the set key method that was generated
| | 09:54 |
earlier and I'll pass in the key value.
And I'll set the initial value of the text
| | 10:01 |
property to an empty string and finally
I'll return the note.
| | 10:07 |
Now, I'll save my changes and I'll see
that there's a little warning here and it
| | 10:11 |
tells me some recommendations for how to
use dates in Java.
| | 10:17 |
This recommendation doesn't apply in this
case so to get rid of the warning click on
| | 10:21 |
the warning icon.
And from the quick fix list that appears,
| | 10:27 |
select the first one, add suppress lint
simple date format to get new.
| | 10:34 |
Suppress lint is a Java directive that
tells the lint tool, that's the tool
| | 10:38 |
that's working in the background, to
examine and tell you about potentially
| | 10:42 |
invalid code.
To not worry about this particular method.
| | 10:48 |
And it's saying specifically don't worry
about the simple date format class.
| | 10:53 |
I know what I'm doing.
So, that's the entire editing for item
| | 10:57 |
class.
It has private fields for the values it
| | 11:00 |
wants to store, public getters and setters
to make those values accessible to the
| | 11:05 |
rest of the application.
And then, a special method to generate a
| | 11:12 |
new instance of the class that populates
the object with the key based on the
| | 11:16 |
current date time stamp.
In the next video, I'll show you how to
| | 11:21 |
create a data source class that starts
putting this class to work.
| | 11:27 |
| | Collapse this transcript |
| Creating a data source class| 00:00 |
After you've created the Java class to
model a single instance of a note.
| | 00:04 |
The next step is to create a Java class
that will manage all of the data.
| | 00:08 |
And this is typically called a data source class.
| | 00:11 |
I'm working in a version of the project
called data source.
| | 00:16 |
And I'll go to my data package that I
previously created, and I'll create
| | 00:19 |
another new class.
I'll call this one notes data source.
| | 00:25 |
And as I did with the note item class,
I'll make this a POJO, by extending the
| | 00:29 |
super class, java dot blank dot object.
I'll click Finish to generate the class.
| | 00:36 |
This class is going to hide all of the
functionality that's used to put, get and
| | 00:41 |
remove data items from the shared
preferences data storage.
| | 00:47 |
And it's going to expose that
functionality through a set of methods.
| | 00:52 |
The first method is going to be called
find all.
| | 00:55 |
And it's going to return a list of notes.
I'll place the cursor within the class
| | 01:00 |
decoration, and I'll create a new method.
It'll be public.
| | 01:05 |
And it's going to return an instance of
something called a list.
| | 01:08 |
In Java, the list is an interface.
I'm going to be saying that I'm returning
| | 01:15 |
a list.
But the concrete implementation of the
| | 01:18 |
list will be something else.
That will be defined within the method I'm
| | 01:22 |
creating.
The list should be notated to say what it
| | 01:25 |
contains.
I'll press Control Space, and I'll select
| | 01:29 |
list.
And that adds the import statement for
| | 01:32 |
that class at the top of my code.
And then it completes the name of the
| | 01:37 |
interface with generic notation.
And being asked to declare here, what kind
| | 01:42 |
of objects this list is going to contain.
And I'm going to type in the name of the
| | 01:48 |
class that I already created Note item.
I'm saying that this method that I'm
| | 01:54 |
defining is going to return a list of note
item objects.
| | 01:58 |
Now I'll name the method, find all, and
I'll ass in the braces to indicate the
| | 02:04 |
body of the method.
I'm going to start by creating a list
| | 02:08 |
containing a single note.
It'll look like this.
| | 02:11 |
First, I'll declare the list itself.
I'll use the same syntax I used in the
| | 02:17 |
return value of the method.
List note item and then I'll name this
| | 02:22 |
item, note list and I'll substantiate it.
Using the constructor method for a class,
| | 02:31 |
called A ray list.
It looks like this.
| | 02:34 |
New, a ray list.
I'll type in the beginning of the class
| | 02:39 |
name.
I'll press control, space and choose a ray
| | 02:42 |
list and notice that eclipse automatically
adds generic notation to indicate the same
| | 02:47 |
member object that I used in the variable
declaration here.
| | 02:53 |
Now I'm declaring the object as a list.
But instantiating with ArrayList.
| | 03:00 |
And that's because ArrayList is a concrete
class that implements the list interface.
| | 03:06 |
I'm using polymorphism to say this is the
class I want to use, but this is the class
| | 03:11 |
I want every one else to think it is.
The nature of an ArrayList Is that it
| | 03:18 |
stores data in the order in which you put
it in.
| | 03:21 |
It doesn't automatically sort anything and
it just always stores it in exactly the
| | 03:25 |
same order.
Next, I'm going to create an instance of
| | 03:30 |
my note item class.
I'll create note item, and I'll call it
| | 03:35 |
note.
And I'll get the instance of the note by
| | 03:38 |
calling that static method that I created
earlier, noteitem.getnew.
| | 03:44 |
So now I have a single note and I'll add
it to the list using notelist.add and I'll
| | 03:48 |
add in my note object.
So now I have a list containing a single
| | 03:55 |
item.
And I'll return it from this code, using
| | 03:59 |
return note list.
I'll save my changes, and make sure that
| | 04:03 |
all the errors and warnings have gone away.
| | 04:06 |
Now I'll be coming back to this method and
filling in a bunch more code later on to
| | 04:10 |
deal with the data that's stored on disk.
But this is enough code to get started and
| | 04:17 |
test this method.
But before I go to testing I'm going to
| | 04:20 |
add two more method signatures, called
updated and remove.
| | 04:25 |
The update method will be used to add or
update a note And it will look like this.
| | 04:31 |
Public boolean update.
So I'm naming the method update and I'm
| | 04:36 |
going to be returning a boolean value, a
true or a false.
| | 04:40 |
The update method will accept an instance
of the note item class, that I'll call
| | 04:45 |
note.
And I'm not going to implement any code
| | 04:49 |
here yet.
I'm just going to return a value of drew.
| | 04:52 |
Finally I'll add the remove method, it
will be very similar to the update method.
| | 04:59 |
It will be public and it will return a
Boolean value.
| | 05:03 |
The name of the method will be remove and
it will receive an argument Data typed as
| | 05:07 |
a note item.
As with the update method, I won't
| | 05:11 |
implement any specific code yet.
I'll just return a true value.
| | 05:17 |
I'll save my change, and review all of the
code in this class.
| | 05:22 |
It has a findAll method that returns a
list of notes, and an update and a remove
| | 05:27 |
method.
Now, I'll go back to the main Activity
| | 05:30 |
class.
This is the class that represents my
| | 05:33 |
primary screen, the screen that's shown as
the application first opens.
| | 05:39 |
Within the main activity class, I'll
declare an instance of my data source
| | 05:43 |
class.
I'll place the cursor after the class
| | 05:46 |
declaration.
And I'll create a private variable.
| | 05:50 |
Data type as note data source.
I'll type in the beginning of the class
| | 05:55 |
name, and press Control Space.
That auto-completes the class name and
| | 05:59 |
adds its import statement at the top.
And I'll name it data source.
| | 06:05 |
Now, I'm only declaring the variable here.
I'm not instantiating it yet.
| | 06:11 |
I have to instantiate it in the on create method.
| | 06:14 |
The method that's called as the
application comes to the screen.
| | 06:19 |
So I'll place the cursor in the onCreate
method after the call to set content view.
| | 06:25 |
And I'll data source equals new notes data source.
| | 06:30 |
As with the note item, I have an
automatically generated no arguments
| | 06:33 |
constructor method that I'm calling here.
Now, to test this, I'm going to call the
| | 06:39 |
find all method of this new object.
And then output the note that will be in
| | 06:44 |
the list that's returned.
I'll declare a list.
| | 06:49 |
Because I'm in a new code set, that is a
new Java class, I have to do the process
| | 06:53 |
of Ctrl+Space and importing the class.
(SOUND) I'll name this notes.
| | 07:02 |
And I'll get it's value from
datasource.findAll the source that I
| | 07:06 |
previously created.
Then, I know I'll have a single note so
| | 07:10 |
I'll retrieve it with this code.
NoteItem note equals notes.get and I'll
| | 07:16 |
pass in a value of zero which means I want
to get the first item in the list.
| | 07:23 |
And then, I'll output the value of the
notes key.
| | 07:27 |
That is the date-time stamp.
I’ll do this using a class called log.
| | 07:34 |
The log class is used to debug Android
applications as they’re running.
| | 07:40 |
Either in an emulator or an actual device.
The log class has to be imported like many
| | 07:44 |
others.
And it's a member of a package called
| | 07:48 |
Android.util.
And it has a series of static methods.
| | 07:52 |
I'm going to use one called i.
The i method is called the info method.
| | 07:59 |
And it's a way of simply outputting a
string or a value that you want to see in
| | 08:02 |
your debug.
It takes two arguments: a tag You should
| | 08:06 |
always use the same value as your tag,
it'll make it easier to debug in the
| | 08:11 |
Eclipse tools.
And then I'm going to output the key of
| | 08:16 |
the note that I just got from the data
source, it'll look like this.
| | 08:22 |
Note, dot, get key.
I'll save my changes.
| | 08:26 |
Now I'm ready for my test.
I'm going to debug the first time I run
| | 08:30 |
the application.
That will trigger the logging
| | 08:34 |
functionality.
Once you've triggered it the first time,
| | 08:38 |
you should be able to run word debug and
see the output in a tool called log kept.
| | 08:45 |
I'll click the Debug button and I'll
choose Android Application.
| | 08:50 |
If you're prompted for the level of logcat
output, choose info or verbose.
| | 08:56 |
I'm not being prompted for that
information because I already answered the
| | 08:59 |
question in a previous session.
I'll switch back to the emulator.
| | 09:05 |
Make sure that the application is running.
Then I'll come back to Eclipse.
| | 09:09 |
And up here I'll go to something called
the DDMS perspective.
| | 09:13 |
With the DDMS prospective selected, I'll
then go down to the log cat tab at the
| | 09:18 |
bottom and double click to Open.
The log cat screen shows all kinds of
| | 09:24 |
information that you may or may not be
interested in.
| | 09:29 |
But to filter it and see only warn
messages, click into the Search Textbox.
| | 09:34 |
And type tag colon and then the name of
your tag.
| | 09:39 |
Which I set as notes.
And here's the result.
| | 09:44 |
I'm getting the key of my note, which is a
daytime stamp with an offset from
| | 09:47 |
Greenwich Mean Time.
If you're using an emulator, the date and
| | 09:51 |
time value could be anything.
But if you're working with an actual
| | 09:56 |
Android device, You should see the date
time and offset from that device.
| | 10:03 |
If you're seeing this value correctly,
then you know that you correctly
| | 10:06 |
instantiating you note, putting it into a
list, returning it from the data source,
| | 10:11 |
and you're ready for the next step,
implementing data persistence with shared
| | 10:15 |
preferences, and we'll get to that in the
next video.
| | 10:20 |
| | Collapse this transcript |
| Adding data to shared preferences| 00:00 |
As I previously described, I'm going to
use shared preferences to store my notes
| | 00:05 |
data on the android device.
The shared preferences architecture
| | 00:10 |
supports storage of key value pairs.
And using the feed Java classes, it will
| | 00:15 |
be possible to sort that data when needed.
I'm working in a version of the project
| | 00:20 |
called shared preferences, and I've opened
the class notes data source.
| | 00:26 |
This data source class will hide all the
details of the implementation of my shared
| | 00:30 |
preferences.
So if I need to make changes to how the
| | 00:34 |
data's being stored in the future, all of
the changes will be confined to this
| | 00:37 |
class.
I'll double-click the Tab of the editor to
| | 00:41 |
go to full screen.
And then, place the cursor after the class
| | 00:45 |
declaration to create an instances of a
shared preferences storage area.
| | 00:51 |
All you have to do is to create an object,
calling a method called get shared
| | 00:55 |
preferences.
Each instance of this shared preferences
| | 00:59 |
data storage will be associated with a
simple string that identifies it, and
| | 01:04 |
makes it sharable for the entire application.
| | 01:08 |
So, I'm going to define a private, static,
final string.
| | 01:13 |
Essentially a constant.
It looks like this.
| | 01:16 |
I'll name it PREFKEY.
The naming convention for constants in
| | 01:22 |
Java is that they're spelled with all uppercase.
| | 01:25 |
And I'll name this preference simply, notes.
| | 01:28 |
Then, I'll declare an instance of a class
called SharedPreferences.
| | 01:33 |
I'll once again make it private.
I'll type in the name of the class,
| | 01:37 |
SharedPreferences.
Then I'll press Ctrl+Space and select the
| | 01:41 |
class from the Android.content package and
that adds an import statement for the
| | 01:46 |
class.
And I'll name this object notePrefs.
| | 01:53 |
Now, I have to instantiate that object I'm
going to instantiate it as the data source
| | 01:57 |
class itself is instantiated.
So to make that happen, I'll create a
| | 02:02 |
public constructor method.
I'll add the keyword public.
| | 02:07 |
And then, the name of the class that I'm
working right now, NotesDataSource.
| | 02:13 |
I type the name of the class and press
Ctrl+Space for autocomplete.
| | 02:18 |
As the data source class is instantiated,
I'm going to ask for the application to
| | 02:22 |
pass in something called the context.
The context is the superclass of an
| | 02:28 |
activity, and it's how we'll connect this
Java class to the higher-level
| | 02:33 |
application.
I'm going to set up this constructor
| | 02:39 |
method to receive the context object.
I'll type in the name of the class
| | 02:43 |
Context.
Press Ctrl+Space and select the class,
| | 02:47 |
that make sure I have an import statement
for it, and then I'll name the argument
| | 02:51 |
context in all lower case.
Within the method, I'll instantiate note
| | 02:59 |
prefs using this code notePrefs equals context.getSharedPreferences.
| | 03:07 |
You have to pass in two arguments to the
get shared preferences method.
| | 03:11 |
The first is the name of the preferences
collection and I identified that using my
| | 03:17 |
constant pref key.
The second argument is something called
| | 03:22 |
the mode.
And for all shared preferences objects its
| | 03:26 |
reccomended that you set a mode of context.mode_private.
| | 03:32 |
That's a constant that's a member of the
context class.
| | 03:35 |
So now as the data source object is
instantiated the shared preferences object
| | 03:39 |
will be instantiated as well.
And if that preferences object doesn't yet
| | 03:45 |
exist, it will be automatically created
for us.
| | 03:48 |
Now, I've made a change to how this data
source class works.
| | 03:52 |
Previously, I didn't have an explicit
constructor method, and Java added a
| | 03:56 |
no-arguments constructor method for me.
But now that I have an explicit
| | 04:01 |
constructor, whenever I instantiate the
class, I must pass in a context.
| | 04:07 |
So, I'll save my changes.
Then, I'll restore the size of the editor.
| | 04:12 |
I'll go down to my problems view at the
bottom of the screen.
| | 04:16 |
And I'll see I have a new error that says
the constructor notes data source is
| | 04:19 |
undefined.
And that's because I have an existing call
| | 04:23 |
to construct the object here in mainactivity.java.
| | 04:28 |
I have to change the way I'm instantiating
the data source object, so I'll place the
| | 04:33 |
cursor inside the data source constructor
method call and pass in this, meaning the
| | 04:38 |
current instance of the activity.
I'll save my changes and that error goes
| | 04:44 |
away.
And now this activity and the data source
| | 04:48 |
are connected.
Now, I need to add code to create new
| | 04:52 |
notes.
As the DataSource class is instantiated, I
| | 04:56 |
now have a SharedPreferences object that I
can use to create and update Note objects.
| | 05:03 |
So, I'll go back to the DataSource class,
and now I'll fill in code in the update
| | 05:07 |
method.
I'll place the cursor inside the existing
| | 05:11 |
update method, and here's the code.
First, create an instance of a class
| | 05:16 |
called SharedPreferences.Editor.
I'll type in shared PRE and press
| | 05:22 |
Ctrl+Space.
I'll select the shared preferences class.
| | 05:27 |
Then, I'll put in a dot and choose the
editor class.
| | 05:31 |
This is a field of the shared preferences class.
| | 05:34 |
And I'll name this new object editor.
And I'll instantiate it using this code
| | 05:41 |
noteprefs.edit.
That means give me an editor object that
| | 05:46 |
knows how to modify data in this
particular shared preferences object.
| | 05:51 |
Now, I'll take the note item object that's
been passed into this update method.
| | 05:57 |
And I'll use its key and text value, and
I'll put the value into the shared
| | 06:01 |
prefrences.
That code will look like this,
| | 06:06 |
editor.putString.
Notice that there are number of different
| | 06:10 |
put methods, including puts for booleans,
floats, ints, longs, and strings.
| | 06:16 |
I'm using this one.
And I'm going to pass in the key of the
| | 06:20 |
current note and the text value of the
current note which I'll get from their
| | 06:23 |
getter methods.
That code will look like this note.getkey
| | 06:28 |
for the first argument and note.gettext
for the second argument.
| | 06:33 |
Finally, after putting the value into the
shared preferences object, you must commit
| | 06:38 |
the changes.
And that code looks like this,
| | 06:43 |
editor.commit.
So, now whenever the update method is
| | 06:48 |
called and a note object is passed in,
that notes key and value will be saved
| | 06:52 |
automatically.
If it didn't exist yet it'll be created
| | 06:57 |
and if it already exists it'll be overwritten.
| | 07:02 |
Now, I'll add code for the remove method.
Much of it will be the same as for the
| | 07:06 |
update method, so I'll select and copy
those first three lines of code and I'll
| | 07:09 |
paste them into the remove method.
For the remove method, instead of calling
| | 07:16 |
putString, we'll call a method of the
Editor object called remove.
| | 07:21 |
So, I'll get rid of that line of code and
I'll replace it with editor.remove, and
| | 07:25 |
I'll pass in note.getKey.
It's a good idea to wrap this code inside
| | 07:30 |
some conditional logic so that you're only
removing preference objects that already
| | 07:35 |
exist.
So, I'm going to place the cursor at the
| | 07:40 |
top of this code and I'll type in the
keyword if.
| | 07:44 |
I'll press Ctrl+Space and select If statement.
| | 07:49 |
That adds a code template for a classic
Java conditional block.
| | 07:54 |
I'll set the condition as follows.
If noteprefs.contains and I'll pass in
| | 08:01 |
note.getkey.
Then I'll take these three lines of code
| | 08:05 |
that are removing the object and move them
to within the conditional block.
| | 08:10 |
And now that code will only be executed if
in fact that particular note already
| | 08:15 |
exists and remember its identified by the key.
| | 08:19 |
Which is the date, time stamp, of when the
note was created.
| | 08:23 |
So, now I have code that can update and
remove notes, and I'll go back to my main
| | 08:27 |
activity and make some changes to fully
test this.
| | 08:32 |
In the, on create method, I already have
code, that's creating my instance of the
| | 08:37 |
data source and the code that's calling
the find all method.
| | 08:43 |
I'll move the cursor after the call to
notes dot get.
| | 08:46 |
And now I'll put the data into the shared
resources object using
| | 08:50 |
datasource.updatenote.
And now each time I run the application,
| | 08:54 |
I'll be adding this note object and saving
it persistently.
| | 09:01 |
I'm not retrieving the data yet I'll show
you how to do that in the next video.
| | 09:05 |
But my goal here is simply to make sure
that I can run the code without the
| | 09:09 |
application crashing or throwing any
significant errors.
| | 09:14 |
So, I'll save all of my changes.
And I'll run the application by clicking
| | 09:19 |
the run button and selecting android application.
| | 09:22 |
So, if the application opens correctly
without crashing, I know I'm executing
| | 09:26 |
code that's working in the background.
But I haven't proved it yet.
| | 09:31 |
To do that, I need to retrieve this data
for persistent storage and see if it's
| | 09:36 |
still around even after shutting down and
restarting my emulator or device.
| | 09:43 |
| | Collapse this transcript |
| Retrieving data from shared preferences| 00:00 |
So far, I've added code to my data source
class, that identifies where the data will
| | 00:04 |
go, a shared preferences object and can
update and remove items from shared
| | 00:08 |
preferences.
Now, I'll add code to retrieve all of the
| | 00:13 |
notes, from my shared preferences object
and return them from the data source
| | 00:16 |
class.
I'm working in a version of the project
| | 00:20 |
called, retrieving data.
And I've opened up the notes data source
| | 00:25 |
class.
And I'm going to modify the find all
| | 00:27 |
method.
The first step is to retrieve data from
| | 00:31 |
the shared preferences object.
And we'll do this using a method called
| | 00:35 |
get all.
It returns an object called a map.
| | 00:39 |
A map is an unordered data collection,
where each item in the collection has a
| | 00:44 |
key and a value.
I'll type the word map and press control
| | 00:50 |
space and select the map interface from Java.util.
| | 00:54 |
Just as with the list, I'm being asked to
identify the data types of the items in
| | 00:58 |
the map.
And now there are two values being asked
| | 01:03 |
for.
The first is going to be a string.
| | 01:06 |
And what I'm saying is that each item is
going to have a string based key.
| | 01:12 |
The second data type is the data type of
the value, and I'm going to put in a
| | 01:16 |
question mark for this, and that's because
the get all method returns a map where it
| | 01:20 |
knows it's a string, but it doesn't know
whether the value is a string, an integer,
| | 01:24 |
a long, and so on.
I'm matching up how the data will be
| | 01:31 |
returned from the shared preferences
object, and how it's going to be received
| | 01:35 |
and processed.
I'll name this new object notes map.
| | 01:40 |
And I'll get its value by calling
notePrefs.getall and notice the signature
| | 01:44 |
of the return object here in the list.
It matches the data type that I used to
| | 01:51 |
declare the notes map object.
I'll double click to Select the method and
| | 01:55 |
Finish the statement.
Now I have retrieved the data.
| | 02:00 |
But the nature of a map is that it's unordered.
| | 02:03 |
That is, it doesn't guarantee that the
data will be in any particular order.
| | 02:07 |
So my next step will be to sort the data
by the keys with oldest notes first and
| | 02:12 |
the newest notes last.
To do that, I'll need to get a list of all
| | 02:18 |
the keys of all the notes in the shared
preferences object, and I'm going to them
| | 02:23 |
into an object called assorted set.
It looks like this.
| | 02:28 |
I'll type SortedSet and press control
space, and that add the required import
| | 02:33 |
statement and auto completes the code.
Than within the sorted set, I'll say this
| | 02:40 |
set contains strings.
And I'll name it Keys.
| | 02:44 |
And I'll get it's value by instanchiating
a class called Tree Set.
| | 02:50 |
Which once again, will contain items of strings.
| | 02:53 |
And within the constructor method for the
tree set, I'll pass in something called
| | 02:59 |
the Key Set method of the map.
Here's how all this code works.
| | 03:03 |
The key set returns a listing of all the
keys for all the notes in the shared
| | 03:08 |
preferences, but in any particular order.
The tree set automatically sorts that data
| | 03:16 |
and returns it in a sorted set.
So by the time I had my sorted set called
| | 03:21 |
keys.
It's already been sorted.
| | 03:25 |
And the default order is the order I want,
from oldest to newest based on the
| | 03:29 |
alphanumeric sort of the date time values.
Now I'm going to loop through those keys
| | 03:36 |
and use the keys to get the items from the
preferences one at a time and add them to
| | 03:41 |
a list object.
I already have the list object here, it's
| | 03:47 |
called note list and I'm going to add a 4 loop.
| | 03:51 |
I'll type 4 and press control, space and
then I'll choose the 4 H code template.
| | 03:58 |
When I add the 4H code template, eclipse
assumes that I'm looping through instances
| | 04:03 |
of note item, but that's not right.
I want to loop through instances of
| | 04:08 |
string.
So I'll change the dated type of the item
| | 04:12 |
I'm looping on to string and the name to key.
| | 04:15 |
And then the collection I'm moving through
to keys.
| | 04:21 |
And here's what I have so far, I'm saying
loop through the list of key values and
| | 04:25 |
deal with the keys one at a time.
Now, for each key, I'll create a note
| | 04:32 |
object.
I'll set the data type as note item, and
| | 04:35 |
name it note.
And I'll instantiate it with equals new.
| | 04:40 |
And I'll call the default constructor
method for the note item class.
| | 04:44 |
Then I'll call Note.SetKey, and I'll pass
in the Key value.
| | 04:50 |
And that's the value that I'm currently
looping on.
| | 04:53 |
I'll make sure the names of the two values match.
| | 04:56 |
So now my Note object has the key, and now
it needs its value.
| | 05:01 |
I'll call Note.SetText, and I'll pass in
the following.
| | 05:06 |
NotesMap.Get and I'll pass in the key.
Now when I save my changes to that, I'll
| | 05:13 |
get an error over here and I'll use the
second available quick fix to cast the
| | 05:17 |
return value to a string because I know my
preferences are strings because that's
| | 05:22 |
what I put into them.
So now at the end of this code I've
| | 05:28 |
created a note object.
And it contains the key I'm looping on,
| | 05:33 |
and the associated string value.
And I'll take that note object, and add it
| | 05:38 |
to my note list.
Using notelist.add, and then I'll pass in
| | 05:43 |
the note object.
And finally, I'll return the note list
| | 05:47 |
object.
I'm going to delete these two lines of
| | 05:50 |
code that I was earlier using for testing.
And that's the completed code for the find
| | 05:55 |
all method.
Now when find all is called, it'll
| | 05:58 |
retrieve the preferences from the shared
preferences object.
| | 06:03 |
It'll sort them using the sorted set and
tree set classes.
| | 06:08 |
It'll loop through the keys and add the
associated notes to the list object and
| | 06:12 |
finally at the end, return the list.
So now let's go back to the main activity
| | 06:19 |
class and review our start up code.
In the main activity class We're creating
| | 06:25 |
an instance of the data source and we're
calling the find all method.
| | 06:30 |
And because we just made those code
changes, we'll now be retrieving the data
| | 06:34 |
that's stored persistently in the shared
preferences object.
| | 06:39 |
Right now, we're simply getting the data.
And we're just getting the first icon and
| | 06:43 |
we're logging it so that we can debug.
And see that we're getting correct data.
| | 06:48 |
But I'm going to add a little bit more
testing code.
| | 06:52 |
After I retrieve that testing note, which
is now coming from persistent storage.
| | 06:56 |
I'll call note.setText.
And I'll pass in a static string of
| | 07:00 |
updated.
So I set the text of the object.
| | 07:04 |
And then I pass it into the update method.
And that updated text value is saved to
| | 07:08 |
persistent storage.
Then I'm going to retrieve the data again.
| | 07:13 |
I once again set the value of notes by
calling data source dot find all.
| | 07:19 |
Notice that I don't have to redeclare the
note's object.
| | 07:23 |
It was already declared above.
Then, once again I'll get the note object
| | 07:27 |
by calling the note's objects get method.
And once again, I don't have to redeclare
| | 07:34 |
the data type, so I'll remove that from
the copied code.
| | 07:38 |
And then I'll log the result, but this
time, I'll log both the key and the value.
| | 07:44 |
After the call to getKey, I'll append a
colon and a space, and then I'll append
| | 07:51 |
note.getText.
I'll save my changes, and I'm ready for a
| | 07:55 |
test.
I'll run the application.
| | 07:59 |
If you see the dialogue asking you how you
want to run the application, select
| | 08:03 |
Android application as before.
Then when the emulator comes to the
| | 08:07 |
screen, wait a moment for the application
to settle.
| | 08:12 |
Go back to Eclipse.
And I'm going to restore the editor.
| | 08:15 |
Depending on your Eclipse configuration
You might see the log cap tab appear over
| | 08:20 |
on the right, or down at the bottom.
I'll double-click it to Expand it.
| | 08:27 |
Then just as I did before, I'll filter, by
adding in tag colon notes.
| | 08:32 |
And there's the result.
The updated note has been retrieved from
| | 08:36 |
persistent storage And shows the value updated.
| | 08:40 |
So if you have that much code working,
you've correctly created a complete
| | 08:45 |
interface for adding, updating, and
removing data from persistent storage
| | 08:49 |
using the shared preferences API.
And we're reading to go on to the next
| | 08:55 |
major step of building our note taking
app, creating the user interface.
| | 09:00 |
And we'll cover that in the next chapter.
| | 09:03 |
| | Collapse this transcript |
|
|
5. Creating the User InterfaceCreating screen designs with layouts and activities| 00:00 |
As you get ready to build a user interface
for an Android app, it's important to know
| | 00:05 |
some basic concepts.
Each Android application has at least one
| | 00:09 |
screen.
And depending on its complexity, it can
| | 00:12 |
have as many screens as are needed.
Each screen needs two elements.
| | 00:18 |
First, an activity, which is a Java class,
and then a definition of the screen
| | 00:24 |
layout.
A screen layout could be very simple, and
| | 00:28 |
be just a container into which you add
your own components at runtime, or it
| | 00:32 |
could define everything that the user sees.
| | 00:36 |
To create a screen layout, you'll create
an XML file.
| | 00:40 |
Each app can have as many layout files as
are needed.
| | 00:45 |
And a single screen can either be built
from a single layout file, from multiple
| | 00:49 |
layout files, sometimes known as fragments.
| | 00:52 |
Or can choose between layout files at runtime.
| | 00:56 |
All layout files have .xml extensions.
And are placed in a layout folder, which
| | 01:02 |
is under a folder called res for resources.
| | 01:06 |
You can create your layout files using
pure XML, or you can use the design tools
| | 01:11 |
that are included in the Android Developer
Tools or ADT.
| | 01:16 |
When you create a layout file, it becomes
something called an app resource.
| | 01:21 |
Each files in the res or resources folder,
is automatically given an ID in an auto
| | 01:27 |
generated Java class named R.
You'll find it in the package explorer
| | 01:33 |
under a folder named gen, or gen for generated.
| | 01:37 |
The ID that's assigned to your resource is
defined by the R class, then the name of
| | 01:42 |
the folder, and then the name of the file
without the file extension.
| | 01:49 |
So, for example, let's say you created a
layout file called activitymain.xml and
| | 01:53 |
you placed it in the layout folder, where
it should be.
| | 01:58 |
That would generate an ID that you can use
to reference the activity at runtime in
| | 02:02 |
your Java code.
And it would be R, the name of the auto
| | 02:07 |
generated class, .layout, matching the
name of the folder, .activity_main.
| | 02:14 |
Notice that the equivalent ID does not
include the file extension.
| | 02:18 |
And that's true for XML files, for PNG
files or graphics, and many other kinds of
| | 02:23 |
resource files.
So, you use the layout file to describe
| | 02:28 |
what your screen looks like, and an
activity to describe how it behaves.
| | 02:34 |
An activity is a Java class, and each
activity manages a single screen of your
| | 02:39 |
application.
As a screen comes up, a method called
| | 02:44 |
onCreat is automatically called.
It's up to you to write the Java code that
| | 02:50 |
loads the layout file that's built for
that activity.
| | 02:54 |
Here's an example.
I have a main activity class that extends
| | 02:59 |
the activity class.
The activity class is a part of the
| | 03:05 |
Android SDK.
Then, I create my own onCreate method, and
| | 03:09 |
it's an override.
Which means that it's overriding the
| | 03:13 |
version of onCreate that's a part of
activity, the super class.
| | 03:17 |
Within the on create method, I call a
method called, set content view, and I
| | 03:22 |
refer to my activity layout file.
So, now I have defined how the activity
| | 03:28 |
and the layout are matched together, and
it's all done in pure Java code.
| | 03:35 |
So, once you understand the difference
between an activity and a layout.
| | 03:39 |
That is, that an activity is a java class,
and the layout is an XML file, and that
| | 03:43 |
they're put together at runtime.
You're on your way to creating the user
| | 03:47 |
interface for Android apps.
And I'll show you how to create the
| | 03:51 |
activities and layouts for this
application in the following videos of
| | 03:55 |
this chapter.
| | 03:56 |
| | Collapse this transcript |
| Displaying lists of data| 00:00 |
In a previous chapter, I described how to
create a data source class, and the class
| | 00:04 |
to model the data that you'll be using in
your application.
| | 00:08 |
Now its' time to display the data using
something called a list activity.
| | 00:12 |
I'm working in a version of the project
called List Screen, which has all of the
| | 00:16 |
previous code, and now I'm going to
transform the main activity.
| | 00:21 |
That is the first screen that's shown when
the app starts into the list activity to
| | 00:25 |
show a list of notes.
I'll start in the main activity class.
| | 00:30 |
When you create a new activity by default
it extends a class called activity and to
| | 00:35 |
show a list of data.
One of the easiest ways is to instead
| | 00:39 |
extend a class called List Activity.
So, I'll delete the Activity class from
| | 00:45 |
the Extends class, and instead I'll set it
to List Activity.
| | 00:49 |
I'll type the beginning of the class name
and press Ctrl + Space to auto complete
| | 00:53 |
it.
Now, I have to follow the rules of the
| | 00:56 |
list activity class.
One of the most important rules is that
| | 01:00 |
the layout for a list activity must
contain something called a list view.
| | 01:06 |
So I'll go to the layout.
ActivityMain.xml and I'm going to delete
| | 01:10 |
the text view object, that was placed on
this layout, when I created it.
| | 01:16 |
Then, I'll go to the composite category
and I'll drag in a list view object.
| | 01:22 |
Don't worry too much, about where it is
placed initially.
| | 01:24 |
Just drop it into place, then click and
drag and move it as far up to the top left
| | 01:29 |
as you can, then drop it again.
Now go into the XML view.
| | 01:36 |
Remove the four padding attributes from
the relative layout tab.
| | 01:41 |
That will cause the list view to expand,
to fill the entire screen.
| | 01:45 |
Then, change the id.
The list activity class has a required ID
| | 01:50 |
for the list view control.
That's how it finds it at run time.
| | 01:55 |
And the required ID looks like this.
Start with the @ character.
| | 02:00 |
Then android in all lower case, then a
colon, ID, then a forward slash and list.
| | 02:09 |
Make sure that it's all lower case and
that there aren't any spaces.
| | 02:12 |
And that's all we have to do in the layout.
| | 02:15 |
Now, let's go back to the main activity class.
| | 02:18 |
I'm going to need to add a bit of code to
update the display.
| | 02:22 |
To retrieve data, and then use something
called an array adaptor class.
| | 02:27 |
The array adaptor class will be used to
wrap around the data, and feed that data
| | 02:31 |
to the list display.
I'm going to be doing this pretty
| | 02:36 |
frequently once the application is finished.
| | 02:39 |
So I'm going to create a special method
for this purpose.
| | 02:43 |
I'll place the cursor in the on create
method, just after the code that
| | 02:46 |
instansiates the data source object.
And I'll call a method that doesn't exist
| | 02:51 |
yet called, refresh display.
Once I finish typing in that line, I get a
| | 02:56 |
quick fix indicator on the left.
It says the method isn't defined.
| | 03:01 |
I'll click it, and I'll select the Quick
Fix to create the method, refresh display.
| | 03:06 |
Now before I implement that method, I'm
going to change some of this code.
| | 03:12 |
First, I'm going to take this code that's
declaring the list of notes and move just
| | 03:16 |
the declaration to the top of the class.
I'll select just the declaration and the
| | 03:23 |
variable name and cut it to the clip board.
| | 03:25 |
Then I'll move up to the top of the class
right after the class declaration and
| | 03:29 |
after the declaration of the data source
and I'll paste it in.
| | 03:34 |
And I'm going to use a variable named this
time of notes list.
| | 03:40 |
I'm not going to instantiate this object
yet, I'm just declaring it.
| | 03:44 |
Now, I'll go back to the On Create method,
and I'm going to get rid of all this other
| | 03:49 |
code.
This was being used for testing and it
| | 03:52 |
will no longer be needed.
Now I'm ready to implement refresh
| | 03:56 |
display.
When the refresh display method is called,
| | 03:59 |
I'll retrieve all the data from the
persistent data store.
| | 04:04 |
So I'll use this code.
Notes list equals data source dot find
| | 04:10 |
all.
Remember the find all method was created
| | 04:13 |
in a previous chapter.
Now I'm going to create an instance of the
| | 04:18 |
Arrayadapter class.
This is a core class of the Android SDK.
| | 04:24 |
I'll type in the beginning of the class
name, press Ctrl + Space, and select the
| | 04:28 |
class from the list.
The Arrayadapter class has generic
| | 04:33 |
notation.
It wants to know what kind of data is
| | 04:36 |
being stored.
And I'll tell it that it will contain
| | 04:40 |
instances of the note item class.
And then I'll name the object adapter.
| | 04:47 |
Then I'll instantiate it using one of the
array adapter classes constructor methods.
| | 04:53 |
I'll start with new.
I'm going to need a little bit more width.
| | 04:56 |
So I'll expand to full screen.
Then I'll type in the beginning of the
| | 04:59 |
class name again, and I'll just select the
first constructor method, signature.
| | 05:05 |
I'm going to be using a different
signature, but this is good for now.
| | 05:08 |
When I construct the array adapter.
It first wants to know the context.
| | 05:14 |
And I'll pass in this for the current
instance of the current activity.
| | 05:20 |
Next, I'm going to tell it how it should
lay our each list item.
| | 05:24 |
And I'm going to use a built in layout
that's included with the Android SDK.
| | 05:30 |
The code looks like this.
Android.R make sure the R is upper case,
| | 05:37 |
then layout, then simple list item 1.
This is an identifier, pointing to a
| | 05:46 |
simple list item that displays a single
text view.
| | 05:51 |
Then I'll pass in my notes list.
And this is how I'll be telling the array
| | 05:55 |
adapter, what data it should be displaying.
| | 05:58 |
So now I have an array adapter that's
wrapped around my data and that's
| | 06:02 |
indicating how the data should be displayed.
| | 06:06 |
And I'm ready to attach the adapter to the
current activity.
| | 06:10 |
I'll call a method called set, list, adapter.
| | 06:14 |
And I'll pass him the adapter variable and
finish the code.
| | 06:19 |
So now whenever refresh display is called,
I'll get the data using the find all
| | 06:23 |
method, I'll wrap the adapter around it,
and I'll attach the adapter to the current
| | 06:27 |
list activity.
I'm ready for a test.
| | 06:32 |
So I'll click the Run button in the
toolbar, and I'll come back to my
| | 06:35 |
emulator.
And when the app opens, it displays
| | 06:39 |
something in the list.
But this is the hash value of the object
| | 06:43 |
that was returned from the data store.
Not it's values.
| | 06:46 |
And that's because my note item classes
tostring method is using the default
| | 06:52 |
tostring method.
That's a part of all Java classes.In order
| | 06:57 |
to display the value that I want, that is
the text value.
| | 07:02 |
I need to override that two string method.
So I'll go back to Eclipse.
| | 07:07 |
And I'll go to my note item class in the
data package.
| | 07:11 |
I'll go down to the bottom of the code.
I'll place the cursor before the closing
| | 07:16 |
brace.
And I'll type in the name of the method I
| | 07:19 |
want to override to string.
I'll press Ctrl + Space, and select the
| | 07:24 |
method.
And that adds in the required method
| | 07:27 |
signature.
I'll get rid of the to do comment.
| | 07:31 |
And then I'll change the return statement
to returnthis.gettext.
| | 07:37 |
I'll save and run again.
And now I'm seeing the correct data
| | 07:40 |
appear.
The text value of the one and only data
| | 07:43 |
object that I added to the data store.
So now my list view is working.
| | 07:50 |
I'm retrieving data from the persistent
data store, the shared preferences.
| | 07:54 |
I'm wrapping the data in an adaptor and
I'm connecting the adapter to the list
| | 07:59 |
activity.
As I add data to the data store, the list
| | 08:03 |
will continually expand to display all of
the notes.
| | 08:07 |
We're not done with the list activity yet.
I'm going to customize its appearance
| | 08:11 |
quite a bit.
Then I'll show you how to do that in
| | 08:14 |
another video.
| | 08:15 |
| | Collapse this transcript |
| Customizing the appearance of list items| 00:00 |
My note taking apps list activity is
correct displaying data from persistent
| | 00:04 |
data storage.
But I'd like to customize the appearance
| | 00:08 |
of each list item.
I'd like to add a visual icon to the right
| | 00:11 |
of the text that gives the user a visual
indicator that they're suppose to touch
| | 00:16 |
the item to edit it.
First, I need to create a graphical icon.
| | 00:21 |
And I need to create a number of different
sizes for various pixel densities.
| | 00:26 |
So, I'll go back to the Android Asset Studio.
| | 00:29 |
The same tool that I used to create my
launcher icons.
| | 00:32 |
I'll go to the generic icons screen.
You can create generic icons from your own
| | 00:37 |
image, from clip art, or from text.
I'll choose clip art.
| | 00:43 |
Then I'll scroll down and I'll choose an
Edit icon, a picture of a pencil.
| | 00:49 |
Some designers prefer a right pointing
carrot for this kind of icon to indicate
| | 00:53 |
that you'll be going from screen to
screen, but I'm being very specific in my
| | 00:56 |
design.
I'm saying when you touch this item,
| | 01:01 |
you'll be editing it.
After I select the graphic, I'll scroll
| | 01:05 |
down a bit, and I'll change the size of
the graphic.
| | 01:09 |
The default is 24 dip and I'm going to
reduce it to 20 dip to better fit within a
| | 01:14 |
list item.
Then I'll set the name of the icon, the
| | 01:19 |
default is ic_example.
And I'll change it toi ic_listitem_edit.
| | 01:27 |
You can name this anything you like as
long as you keep it all lower case, and
| | 01:30 |
don't include any spaces.
I'll scroll down and look at the preview,
| | 01:35 |
then I'll download the zip file that was
created for me.
| | 01:39 |
Once the zip file has been downloaded,
I'll go to Finder or Windows Explorer for
| | 01:44 |
Windows, and then I'll extract the
contents of the zip file.
| | 01:50 |
The zip file has a folder called res for
resources, and three folders for three
| | 01:55 |
different sizes of graphics.
I'll select all and copy, go back to
| | 02:01 |
Eclipse, go to the res folder of my
application, and paste those folders in.
| | 02:09 |
When prompted, I'll say yes.
I want to override.
| | 02:12 |
And now my graphics for editing are a part
of the application.
| | 02:17 |
Notice that I'm working in a project
called List items, and this is a
| | 02:21 |
continuation from a previous exercise.
So, now I have my graphic, and I need a
| | 02:27 |
way to display the graphic next to the
text value of each note.
| | 02:32 |
To do this, I'm going to create a custom layout.
| | 02:35 |
Layouts always go in the custom folder
under res.
| | 02:39 |
So, I'll go to that folder, I'll right
click on it.
| | 02:44 |
And I'll choose new > Android XML file.
In this dialog box, I'll make sure the
| | 02:50 |
resource type is set to layout.
That's the default, and I'll set the file
| | 02:55 |
name to list_item_layout.xml.
Just as with any resource, the ID has to
| | 03:02 |
be all lower case with no spaces.
I'll click Finish, and that creates the
| | 03:08 |
layout.
The layout first opens in WYSIWYG mode.
| | 03:14 |
I'll look at it in XML mode, and show that
it starts as a linear layout.
| | 03:18 |
And I'm going to make a whole bunch of
changes here.
| | 03:21 |
The default layout that I'm already using
for my list items consists of a single
| | 03:25 |
text view object.
I'm just going to replace that Text View,
| | 03:30 |
and I'm not going to wrap any other
objects around it.
| | 03:34 |
So, I'll change the route element of this
XML file from linear layout to Text view.
| | 03:38 |
Next, I'll change the width from match
parent to fill parent.
| | 03:45 |
And that's saying that this text view
object should expand to fill all available
| | 03:49 |
horizontal space.
Then I'll change the layout height from
| | 03:53 |
match_parent to wrap_content, so that the
height matches whatever font size I assign
| | 03:58 |
to the text field.
I don't need the orientation attribute
| | 04:03 |
that was for the linear layout and doesn't
apply to the Text view.
| | 04:08 |
But I do need a number of other settings.
First, I'll set the gravity.
| | 04:15 |
The gravity determines where the text
falls vertically.
| | 04:19 |
And I'll set its value to center_vertical,
and that will cause the text to have the
| | 04:24 |
same amount of space above and below.
Next, I'll set padding to 5dp.
| | 04:30 |
That means add a little bit of space
around the text, so that the text values
| | 04:34 |
aren't crammed right next to each other.
Next, I'll set the display to single line.
| | 04:43 |
Setting single line equals true.
And that means that even if the text value
| | 04:47 |
has more than one line, only show one of
the lines.
| | 04:52 |
And finally, I'll set the text size to 20 sp.
| | 04:57 |
You can play with this size and get the
size that you want, but this size feels
| | 05:01 |
readable on a variety of devices to me.
Now, I'm going to add a couple of other
| | 05:06 |
special features.
If a note's text value is too long to fit
| | 05:11 |
on a single line, by default it just truncates.
| | 05:15 |
But I'd like to show ellipses, three dots
at the end of the line.
| | 05:20 |
To do that, add an attribute called
ellipsize, and set it's value to n.
| | 05:25 |
And then if the text is too long to fit in
the available space, you'll get those
| | 05:30 |
three dots.
And finally, I'll add my graphic.
| | 05:35 |
Notice that I'm only doing this with the
single control or a single view.
| | 05:40 |
I don't have a layout combining a text
view and a graphic.
| | 05:44 |
Instead, I'll use an attribute of the text
view Called drawable right.
| | 05:50 |
You can add a drawable component to the
left, right, start, end, top, or bottom.
| | 05:57 |
By saying you want a drawbable right, the
icon will always appear on the far right
| | 06:01 |
side of the Text view no matter how long
the text is.
| | 06:06 |
And I'll set that to the ID of the icon
that I created, using @drawable, that's
| | 06:10 |
the name of the resource folder in which
it's stored, and then the ID of the icon.
| | 06:17 |
IC list item edit, and that's my new
custom layout for each item in my list.
| | 06:25 |
I'll save those changes, and I'll go back
to the main activity.
| | 06:30 |
In the main activity, I'm currently
assigning the built in layout, simple list
| | 06:35 |
item one.
And I'm going to replace that with my own
| | 06:39 |
custom layout that I just created.
And that will be r.layout.listitemlayout.
| | 06:48 |
Each time you create a new layout, an ID
for it is created in the automatically
| | 06:52 |
generated R class.
The next value is the name of the folder
| | 06:57 |
layout, and the next value is the ID of
the layout file without the .xml
| | 07:01 |
extension.
I'll save and test my code.
| | 07:06 |
And now, the list item is displayed with
its text value, and with the graphical
| | 07:11 |
icon on the right side.
As I add more items to the list, I'll see
| | 07:16 |
one instance of the graphical icon for
each list item.
| | 07:21 |
And the user we'll know by seeing the
icon, that they can touch that item and
| | 07:26 |
edit its value.
| | 07:28 |
| | Collapse this transcript |
| Creating the editor activity and layout| 00:00 |
My note taking app will require two screens.
| | 00:03 |
The lists screen, which I've already
created, and an editor or detail screen.
| | 00:08 |
When the user touches one of the notes in
the list, they'll be taken to the editor
| | 00:12 |
screen.
The text value of the selected note will
| | 00:15 |
be displayed, the user will be allowed to
edit it and when they return to the list
| | 00:19 |
screen, their changes will be saved automatically.
| | 00:23 |
To create the second screen, you'll need
to create two files.
| | 00:27 |
A layout and a Java class.
I'll start with the layout.
| | 00:32 |
I'm working on a version of the project
called editor activity that continues from
| | 00:35 |
the previous exercise.
I'll go to the layout folder within the
| | 00:39 |
resources section.
I'll right-click on that folder, and
| | 00:45 |
select New > Android XML File.
The Resource Type is Layout.
| | 00:51 |
And I'll set the file name to activity_note_editor.xml.
| | 00:58 |
The default route element for this new
layout is a linear layout.
| | 01:01 |
I'm instead going to choose Relative layout.
| | 01:04 |
This will allow me to more easily control
the positioning of the contained object.
| | 01:10 |
Which will simply be a text editor object.
I'll click finish and that creates the XML
| | 01:16 |
file.
I'll then double click to open the XML
| | 01:19 |
file if it didn't open automatically, and
that opens the file.
| | 01:24 |
If your file opened to the graphical
interface as mine did, click on the XML
| | 01:28 |
tab at the bottom And you'll see that the
starting layout is simply a root element
| | 01:33 |
of a relative layout.
Now go back to the graphical layout and
| | 01:38 |
we'll add in a text field.
Click on the text field section in the
| | 01:42 |
palette and then click and drag a plain
text text field and then drop it into the
| | 01:47 |
activity.
Don't worry about where you're dropping it
| | 01:52 |
initially.
Or changes positioning and size when we
| | 01:55 |
get back to the raw XML view.
Now go back to the raw XML view, and we'll
| | 02:00 |
make some changes.
First change the ID.
| | 02:04 |
The default is edit text one.
Change it to note text.
| | 02:10 |
That's the ID we'll use in our Java code
to address this object.
| | 02:14 |
Next, change both the width and height
from wrap content to fill_parent.
| | 02:21 |
That will cause the edit text object to
fill all available space.
| | 02:26 |
Then remove both align attributes that
were generated for you.
| | 02:31 |
You don't need those.
And also, remove the margins.
| | 02:34 |
Now, look at the object in graphical layout.
| | 02:36 |
And you'll see that the object has
expanded to fill all available space.
| | 02:41 |
Now we'll set some attributes that are needed.
| | 02:46 |
Place the cursor inside the beginning tag
and we'll add these attributes, set single
| | 02:51 |
line to false, that will make sure that
the user can add multiple lines to the
| | 02:56 |
note, including pressing a return button
to add a line feed.
| | 03:02 |
Next, set the gravity attribute to top.
This will cause the text to start at the
| | 03:07 |
top of the Edit Text control, regardless
of how long it is.
| | 03:11 |
Next, set the inputType attribute to
textMultiLine, and that's it.
| | 03:18 |
Your layout is complete, and you can now
use this layout in an activity.
| | 03:24 |
The next step is to create a Java class
for the new activity.
| | 03:27 |
Go to the Source folder in your package
explorer and go to the default package,
| | 03:32 |
right click and select New Class.
Set the name of the class to note editor
| | 03:40 |
activity and then set the super class to activity.
| | 03:47 |
Make sure you're using the activity class
in the Android.app package.
| | 03:52 |
Click finish, and your new class has been created.
| | 03:56 |
Now, before we fill in any of this code.
We need to register this class with the
| | 04:01 |
application manifest.
Go to androidmanifest.xml.
| | 04:06 |
You'll find it at the bottom of the
package explorer.
| | 04:08 |
Double-click to open it.
And then, click on the Android
| | 04:13 |
manifest.xml tab at the bottom of the editor.
| | 04:16 |
I’ll expand to full screen.
And then we just need to add a new
| | 04:21 |
activity element inside the application
that ensures that our new activity class
| | 04:26 |
is loaded with the application.
Place the cursor after the end tag of the
| | 04:32 |
existing activity.
And add a new line.
| | 04:36 |
Add a new activity tag, set its name
attribute to dot, and then the name of
| | 04:43 |
your new job of class. NoteEditorActivity.
| | 04:51 |
Then, complete the tag with empty tag syntax.
| | 04:53 |
You don't need any other attributes, also,
because I put a dot before the name of the
| | 04:58 |
class, I didn't need to include the entire
package name.
| | 05:03 |
You can if you want to, but it's not
required as it is with the main activity.
| | 05:08 |
Save your changes to the manifest and now
go back to the new java class.
| | 05:13 |
Note editor activity.
As this activity comes to the screen it
| | 05:17 |
has to load its layout so we'll need to
create an override of the on create
| | 05:21 |
method.
That's the method that's called
| | 05:25 |
automatically, as the activity appears.
Place the cursor inside the class
| | 05:30 |
declaration, type oncreate, press CTRL
Space and choose the first item in the
| | 05:35 |
list.
And that generates the onCreate method
| | 05:40 |
signature.
Remove the to do comment, place the cursor
| | 05:44 |
after the call to super.onCreate and then
call setContentView.
| | 05:50 |
And passing the id of your new layout. R.layout,activity_note_editor.
| | 05:55 |
And now the two files are bound together.
The Java class, the activity is registered
| | 06:01 |
in the application manifest and as the
activity is opened.
| | 06:08 |
It loads its own way out.
So far this activity isn't completely
| | 06:12 |
integrated into the application.
There's no way to go to it yet.
| | 06:16 |
But we'll handle that in the next video,
when I describe how the navigational
| | 06:21 |
pattern of this application is going to
work.
| | 06:25 |
| | Collapse this transcript |
| Creating an action bar command item| 00:00 |
We've created our screen definitions, and
now it's time to add a user interface for
| | 00:04 |
navigation.
The first step is to add an icon that lets
| | 00:08 |
the user indicate that they want to create
a new note.
| | 00:13 |
On newer devices, I'll do this with the
Action bar.
| | 00:16 |
The Action bar was introduced in
Honeycomb, Android 3.
| | 00:21 |
And it's a way of adding command icons to
the top of the application next to the
| | 00:25 |
name of the application and the launcher icon.
| | 00:29 |
I'm working in a version of the
application called Action bar.
| | 00:34 |
And I'll start by creating a new graphical
icon to use in the Action bar.
| | 00:39 |
I'll go back to the Android Asset Studio,
and this time, I'll click on Action bar
| | 00:44 |
and Tab Icons.
I'm going to once again use clipart to
| | 00:48 |
create my icons.
You could create your own images if you
| | 00:52 |
prefer.
I'll click the clipart section, and I'll
| | 00:55 |
scroll down till I find the plus icon.
This is clearly an indicator that I want
| | 01:01 |
to create something new.
I'll select the item, and I'll scroll down
| | 01:06 |
a little bit further.
I'll set the name of the icon to
| | 01:11 |
create_note.
The help text on the left indicates that
| | 01:16 |
this string will be appended to
ic_action_, then I'm going to set the
| | 01:21 |
theme to holo dark.
This will match the look of my
| | 01:26 |
application's action bar because of the
theme that I selected when I created the
| | 01:30 |
app.
Now, I'm ready to download the zip file.
| | 01:35 |
I'll click and download.
I'll go to the Finder window, or Windows
| | 01:38 |
Explorer.
I'm going to get rid of some of these
| | 01:41 |
older files, I don't need them anymore.
And then I'll extract the zip file that I
| | 01:46 |
just created.
As before, I'll have folders for the
| | 01:51 |
different pixel densities.
And the names of the files will match what
| | 01:55 |
I requested in the Asset Studio.
I'll come back to the Resources folder,
| | 02:00 |
Select All and Copy, and then return to Eclipse.
| | 02:05 |
I'll go to the resource folder and I'll
paste into resources and overwrite all.
| | 02:12 |
And that adds the graphics to my drawable folders.
| | 02:17 |
Now, I'm ready to use those graphics in my
action bar.
| | 02:21 |
The next step is to modify a Menu file.
Menu files are defined as XML files, and
| | 02:28 |
they're also in resources.
When you created the new application, it
| | 02:33 |
was automatically populated with this
default Main menu file.
| | 02:37 |
And it has a single item with an ID of action_settings.
| | 02:41 |
Our application isn't going to have any
preferences or special settings.
| | 02:46 |
So, I'm just going to reuse this item.
When you create an item in a menu, it can
| | 02:52 |
either show up in a menu or in the action
bar, and that's determined by this
| | 02:57 |
attribute, showAsAction.
I'm going to change the value of
| | 03:02 |
showAsAction to always.
Then I will change the idea of this item
| | 03:08 |
from action_settings to action_create.
I'm also going to reset the title.
| | 03:14 |
Right now, it's using a string resource
that's in the strings.xml file.
| | 03:20 |
I am going to jump to that file, I'll hold
down the Cmd key on Mac or Ctrl on
| | 03:25 |
Windows, and then click the item.
And that jumps to the item in the
| | 03:31 |
strings.xml file.
This file is actually in the values folder
| | 03:35 |
here.
I'll change the name of this resource from
| | 03:39 |
action settings to action_create, and
change its value to create.
| | 03:45 |
And then, while I'm in this file, I'll do
a little bit of cleanup.
| | 03:49 |
I'm not saying, hello plain old notes anymore.
| | 03:53 |
So, I'll delete that string resource and save.
| | 03:55 |
I'll come back to the Main menu, and now I
see an error on the title because that
| | 04:00 |
resource doesn't exist anymore.
And I'll change it from action settings to
| | 04:06 |
action_create.
Now, let's go back to the icon.
| | 04:10 |
Remember that I created the icon and added
it to the resources.
| | 04:15 |
So, I'll add an icon attribute, and I'll
set it to the ID of my new icon
| | 04:20 |
@drawable/ic_action_create_note.
If there's room, I'd like to show both the
| | 04:27 |
icon and the create text.
To make that happen, I'll go back to
| | 04:32 |
showAsAction and I'll add a pipe
character, and then after that, withText.
| | 04:38 |
And that means if you have space, show the
text, but if you don't, just show the
| | 04:42 |
icon.
Now, that's pretty much all I need to do
| | 04:46 |
to display the icon and that's because my
main activity class already has the code
| | 04:51 |
to load the menu.
You'll find that in MainActivity.Java down
| | 04:57 |
toward the bottom in the On Create Options
menu method.
| | 05:01 |
Here, it's inflating the main menu and
adding it to this activity.
| | 05:06 |
So, it's time for a test.
I'll run the application, and when it
| | 05:11 |
reloads in the emulator, the plus icon is displayed.
| | 05:16 |
Right now it's not doing anything, but
we'll add functionality to it later.
| | 05:20 |
But I'm also going to test in a tablet.
I'll go back to Eclipse, I'll click the
| | 05:27 |
down arrow next to the Run button and
choose Run Configurations.
| | 05:33 |
When the Action Bar project opens, I'll
click on Target, and then select Always
| | 05:38 |
Prompt to Pick Device.
I'll click Run, and then I'll launch a new
| | 05:44 |
Android Virtual Device from my tablet
device which is emulating a Nexus 7
| | 05:50 |
running Jelly Bean.
When the emulator for the tablet loads, it
| | 05:57 |
shows the icon on the right, including
both the plus icon and the text that I
| | 06:02 |
requested.
In this emulator, I had previously added
| | 06:07 |
some data.
And now, we're seeing how the list
| | 06:10 |
activity will look when I populated it
with more than a single note.
| | 06:15 |
I'm still not able to go to the detail
editor screen, but we'll see how to do
| | 06:19 |
that in the next video.
When I describe how to wire up the event
| | 06:23 |
that occurs when the user touches the
create icon in the Action bar.
| | 06:28 |
| | Collapse this transcript |
| Creating a new note| 00:00 |
In our application, I've created two
screens and added an action bar item that
| | 00:04 |
allows the user to say they want to create
a new note.
| | 00:08 |
Right now though, the Action Bar icon
doesn't do anything.
| | 00:12 |
Now I'm going to add functionality so that
when the user touches the Action Bar add
| | 00:16 |
icon, a new note object is created in memory.
| | 00:20 |
And then the screen changes to the editor screen.
| | 00:24 |
The user will then be able to touch the
Back button on the device or a Back button
| | 00:28 |
that's a part of the application to return
to the list screen.
| | 00:32 |
I'm working in a version of the
application called create note that
| | 00:36 |
continues from the last exercise and I'll
start in the main activity class.
| | 00:42 |
When the user selects an item in the
Action Bar or in the Options menu, which
| | 00:47 |
we're not using right now, it triggers a
method called on options item selected.
| | 00:53 |
I need to create an override of that
method in my class so I'll move the cursor
| | 00:58 |
to after the existing code and I'll start
typing the name of the method,
| | 01:02 |
onoptionsitem.
Then I'll press Ctrl + Space and select
| | 01:08 |
the method from the list that's presented.
That creates the method signature.
| | 01:14 |
I'll delete the to do comment, and then
add co before the return statement.
| | 01:20 |
When onoptionsitem selected is called in
the menu item that was selected as an
| | 01:26 |
object.
The name of that argument is item.
| | 01:29 |
So you could evaluate which item was
selected by looking at a method called get
| | 01:34 |
item ID.
My menu only has one item but I'll make
| | 01:38 |
absolutely sure that the right one was
selected using an if statement.
| | 01:43 |
I'll type if, and press Ctrl + Space and
choose the if code template.
| | 01:49 |
Then I'll set the condition as follows.
Item.getItemId is equal to
| | 01:54 |
R.id.action_create and that's the ID of
the menu item that I created.
| | 02:02 |
If that item was selected from the menu,
I'll call another method called create
| | 02:07 |
note.
I'll type the name of the method, which
| | 02:11 |
doesn't exist yet, then I'll press Cmd + 1
on Mac, or Ctrl + 1 on Windows, and select
| | 02:16 |
a quick fix to create the method.
I'll scroll down to the new method, I'll
| | 02:22 |
delete the to do comment, and I'll
implement this method.
| | 02:27 |
First I need to create a new note object.
I'm going to create it here in the main
| | 02:32 |
activity, then pass it to the editor activity.
| | 02:36 |
I'll declare a new note object, data type
does note item and I'll get the object by
| | 02:40 |
calling the get new method of the new note
item class.
| | 02:45 |
Now, I'm ready to create Navigation
between the two screens.
| | 02:49 |
To navigate from one screen to the next,
I'll create an intent object.
| | 02:54 |
I'll type in the name of the intent class
and I'll choose it from the list to make
| | 02:58 |
sure I have the right import and I'll name
the object intent in all lower case.
| | 03:04 |
I'll instantiate it using intent classes
instructor new intent.
| | 03:10 |
And I'll pass in the first argument as
this, meaning the current activity or
| | 03:14 |
context.
And then I'll indicate which class I want
| | 03:19 |
to use to create the new activity.
And that will be NoteEditorActivity.class.
| | 03:26 |
Notice that you don't pass in an instance
of the activity, you're simply telling
| | 03:30 |
Android which class to use.
And then Android instantiate the class for
| | 03:36 |
you.
Next, I need to pass data to the new
| | 03:39 |
activity.
For that, I'll use a method called put
| | 03:44 |
extra.
It's possible to create a complex object
| | 03:48 |
and pass the entire object.
But it takes quite a bit more code than if
| | 03:52 |
you're just passing a couple of simple values.
| | 03:55 |
If you want to learn how to pass complex
objects, take a look at my course, Android
| | 03:59 |
SDK Local Data Storage.
I described the process there.
| | 04:04 |
But if you're only passing a couple of
simple strings as we're going to do here,
| | 04:08 |
it's easier just to call the put extra
method a couple of times.
| | 04:13 |
So I'm going to call Intent.putextra.
Notice the put extra method has a number
| | 04:19 |
of different signatures.
They all require a string as the first
| | 04:23 |
argument, but then you can send a
different types of data as the second
| | 04:27 |
argument.
We're going to use this one.
| | 04:32 |
Put extra for passing a string.
The first argument identifies the value
| | 04:38 |
that's being passed in and I'm going to
give that a value of key.
| | 04:42 |
Then, I'll pass in the note object's key,
calling note.getkey.
| | 04:50 |
Remember that the key is generated as a
date, time stamp indicating to the second
| | 04:54 |
when the note was created.
Then I'll call intent.putextra again.
| | 05:00 |
This time I'll pass in a first argument of
text, and I'll pass in note.getText.
| | 05:07 |
So now the intent object is an envelope.
It contains all the information that's
| | 05:12 |
needed to navigate to the new screen.
The activity that's going to be used and
| | 05:17 |
the values, the key and the text of the
current note.
| | 05:22 |
And I'm ready to start the activity.
I'll call a method called start activity
| | 05:26 |
for result.
There are a couple of signatures for this
| | 05:29 |
one.
I'll choose the first one.
| | 05:32 |
The first argument is the intent.
And the second is something called a
| | 05:36 |
request code.
The request code is an integer value.
| | 05:40 |
When you start the activity, you pass in
the request code.
| | 05:44 |
When the activity is finished, it passes
back the request code.
| | 05:48 |
And when the first activity receives the
request code it can figure out which
| | 05:52 |
screen it came from.
The request code integer can be anything.
| | 05:56 |
I'll pass in a value of 1001.
Later on when I clean up this code, I'll
| | 06:00 |
turn that into a constant but that's good
for now.
| | 06:05 |
So now my create note method is creating
the note object It's creating the intent
| | 06:10 |
indicating what screen I want to go to.
It's passing in the data and it's starting
| | 06:17 |
the activity.
Now let's go to the editor activity.
| | 06:20 |
I'll open NoteEditorActivity.Java.
And I have some work to do here.
| | 06:26 |
First, I'll declare a persistent note item object.
| | 06:32 |
Within the task declaration, I'll create a
private field data typed as note item, and
| | 06:37 |
I'll call it note.
In the on create method, which is called
| | 06:42 |
automatically as the activity starts up,
I'll once again get a reference to the
| | 06:47 |
intent.
I'll create a variable called intent, data
| | 06:52 |
typed as intent, and I'll get its
reference by calling this.getIntent.
| | 06:57 |
This now gets referenced to the same
intent object that was created by the
| | 07:02 |
first activity.
Next, I'll instantiate the note object
| | 07:07 |
that I already declared.
Note equals new note item.
| | 07:11 |
Then I'll populate it with the values.
This time by calling the intent
| | 07:17 |
getStringExtra method.
The code looks like this: note.setKey, and
| | 07:22 |
I'll pass in intent.getStringExtra.
And I'll pass in the key value that I used
| | 07:29 |
in the main activity Key.
Once again, when I clean up all this code,
| | 07:34 |
I'll turn these strings into constants, to
make sure I'm using the same values every
| | 07:39 |
time.
So I've retrieved the key and saved it in
| | 07:44 |
my note object.
I'll do the same thing for the text value,
| | 07:48 |
with note.setText.
And I'll again call intent.getStringExtra,
| | 07:54 |
and I'll pass in text.
So now I've reconstructed the note object
| | 07:58 |
as the editor activity starts up.
And I'm ready to display the note's text
| | 08:04 |
value in the edit text control that's a
part of this layout.
| | 08:09 |
I'll create a reference to the edit text object.
| | 08:13 |
I'll declare a new variable, data typed as
edit text.
| | 08:17 |
I'll be sure to include an import and I'll
name it et and then I'll call findViewbyId
| | 08:23 |
and I'll pass in r.id.noteText that's the
edit text object id that I created in the
| | 08:29 |
layout.
When I finish the line of code I have an
| | 08:35 |
error and that means that I need to add a
quick fix and set the casting And set the
| | 08:39 |
casting of the return value as an edit
text object.
| | 08:44 |
Next, I'll set the text property of the
edit text object.
| | 08:48 |
I'll call et.setText and I'll pass in note.getText.
| | 08:53 |
And finally, because this code is going to
be exactly the same, regardless of whether
| | 08:58 |
I'm creating a new note or editing an
existing note.
| | 09:04 |
I'll place the cursor at the end of the
existing text value.
| | 09:09 |
With this code, et.set selection and then
I'll pass in note.getText.length.
| | 09:16 |
And that's all the code I need to receive
the values that were sent in by the main
| | 09:22 |
activity.
Save them persistently in the private note
| | 09:28 |
object and then display the value of the
notes text so that the user can add, edit,
| | 09:33 |
or remove it.
I'm ready to test the application again.
| | 09:37 |
I'll run the application in the emulator
and when I click the Plus icon, I'm taken
| | 09:42 |
to the editor's screen where I can start
typing my notes value.
| | 09:48 |
Saying this is a new note.
Now for the moment, when I click the Back
| | 09:52 |
button, nothing happens.
I'm not actually creating the note yet.
| | 09:57 |
That will come in a later exercise.
But I've successfully linked the two
| | 10:01 |
screens together, allowing the user to
start at the list screen and then click
| | 10:06 |
the Action Bar icon to navigate to the
editor screen.
| | 10:11 |
| | Collapse this transcript |
| Editing an existing note| 00:00 |
At this point, the note-taking app has the
ability to add a new note and view it in
| | 00:04 |
the editor, and return to the list screen
but not yet to save the note to persistent
| | 00:08 |
storage.
Before I get to that step, though, I'd
| | 00:13 |
also like the user to be able to touch one
of the existing notes and be able to open
| | 00:17 |
up that note in the editor screen.
And it turns out that that takes a very
| | 00:22 |
small amount of additional code.
I'm working now in a project called edit
| | 00:26 |
note.
Which continues from the last exercise.
| | 00:29 |
And I'll start in the main activity class.
The main activity class extends list
| | 00:34 |
activity.
And that class has a method called
| | 00:38 |
onlistitemclick.
This method is called automatically when
| | 00:42 |
the user touches one of the items in the list.
| | 00:45 |
When the method is called, you'll receive
arguments that tell you which item was
| | 00:49 |
selected and you'll be able to manipulate
the application from there.
| | 00:54 |
So, I'll go down to the bottom of the
code, I'll go into Full Screen, and I'll
| | 00:58 |
place the cursor after the last method, createNote.
| | 01:04 |
And I'll create a new method called
onlistitemclick because this is an
| | 01:07 |
override.
All I have to do is type the name of the
| | 01:11 |
method, press Ctrl space and select a
method from the list that appears and that
| | 01:15 |
creates the overwrite signature.
I'll remove both the to do comment and the
| | 01:21 |
call to the super classes version of this method.
| | 01:25 |
And I'll implement my own version.
The first thing I need to do is get a
| | 01:29 |
reference to the Note object that the user
selected, and this is available through
| | 01:34 |
the position argument, which is passed in
as the third argument of the method.
| | 01:40 |
I've already stored my data persistently
in this class as a list called notesList.
| | 01:46 |
So, I'll get a reference to the selected
note item by using the notesList and it's
| | 01:50 |
get method, and passing in the position argument.
| | 01:55 |
That code will look like this.
NoteItem note equals notesList.get.
| | 02:02 |
And I'll pass in the position argument.
So, now I have the note the user selected.
| | 02:10 |
And the rest of the code is identical to
how I pass data in createNote.
| | 02:15 |
So, I'm going to select and copy that
code, starting with creating the intent,
| | 02:20 |
and I'll paste it into the onlistitemclick
method after I've created the Note object.
| | 02:27 |
And that's it, now when the user selects
one of the objects by touching it, this
| | 02:31 |
method will be called and the note will be
opened in the editor screen.
| | 02:37 |
I'll save my code and run the app in my Emulator.
| | 02:41 |
I'll click with my mouse to simulate the
touch event, and the note is opened in the
| | 02:45 |
editor screen.
Once I'm in the editor, I can add new
| | 02:49 |
text, new lines and so on.
But when I click the Back button, I come
| | 02:53 |
back to the list screen and that's because
I haven't added the code that will be
| | 02:57 |
needed to save this data to persistent storage.
| | 03:01 |
I'll take care of that task in the next
video.
| | 03:04 |
| | Collapse this transcript |
| Saving notes to persistent storage| 00:00 |
The note taking app now has the ability to
add a new note to the editor, allowing the
| | 00:05 |
user to type in new information or to edit
an existing note.
| | 00:12 |
But in neither case is it saving changes
to persistent storage.
| | 00:16 |
And that's the feature that I'll add next.
I'm working in a version of the project
| | 00:20 |
called save note that continues from the
last exercise.
| | 00:25 |
The first step in saving data, is to pass
data from the editor activity back to the
| | 00:30 |
main activity.
So, I'll go to the note editor activity
| | 00:34 |
class I'll expand to full screen and I'm
going to add a couple of features.
| | 00:40 |
First of all, I'm going to add a new
method that I'll call, save and finish.
| | 00:46 |
When you go from one activity to another
activity, returning to the previous
| | 00:50 |
activity is called finishing.
And there's a method named finish you can
| | 00:55 |
use to make that happen.
But before you call that method, if you
| | 00:59 |
want to pass data back, you have take a
few other steps.
| | 01:03 |
I'll create a new private void method,
that I'll call saveAndFinish.
| | 01:07 |
The first step when the user touches the
back button, is to get the text that
| | 01:11 |
they've typed into the editor.
To do that, I'll use this bit of code
| | 01:16 |
that's getting a reference to the EditText object.
| | 01:20 |
I'll copy and paste that into the new method.
| | 01:23 |
Then, I'll declare a new variable data
typed as a string that I'll call noteText.
| | 01:28 |
And I'll get it's value, by calling et,
that's the variable pointing to the
| | 01:35 |
EditText object, .getText.toString.
Be sure to use the to string method, if
| | 01:42 |
you just reference he getText method, you
won't get a valid string.
| | 01:47 |
So, now I have the value that the user has
entered or updated and I'm ready to
| | 01:50 |
package it to send it back to the main activity.
| | 01:55 |
For that purpose, I'll use an intent object.
| | 01:58 |
I'll create a new intent variable and I'll
instantiate it using the intent class's
| | 02:03 |
constructor method.
Then, I'll put the values in that I want
| | 02:08 |
to pass back to the main activity.
This code will be almost exactly the same
| | 02:13 |
as when I passed data from the main
activity to the editor activity.
| | 02:19 |
So, I'll go to the main activity and copy
these two lines of code that are calling
| | 02:22 |
the intent object's putExtra method.
I'll go back to the editor and paste that
| | 02:28 |
code in.
This time, I'm referring to the key of the
| | 02:31 |
note object that I saved persistently when
the editor opened and so I'm passing the
| | 02:36 |
key back to the main activity.
For the text though, I want to pass the
| | 02:42 |
value that the user typed in.
And that's the variable noteText.
| | 02:48 |
So, now I have an intent wrapping the data
to send back and I need to send a message
| | 02:52 |
back to the main activity saying,
everything's okay, save this data.
| | 02:58 |
I'll call a method called setResult, and
I'll pass in two values, a result code,
| | 03:04 |
and an intent.
For the result code, I'll use a constant
| | 03:08 |
of the activity class called RESULT_OK.
And for the intent, I'll pass in the
| | 03:13 |
intent object that I've just created.
And now, I'm ready to go back to the main
| | 03:19 |
activity.
And I'll call a method called finish.
| | 03:23 |
The finish method simply means, I'm done.
Go back to the activity that called this
| | 03:29 |
one.
Next, I need to provide a way of calling
| | 03:32 |
this method.
This method will be called in one of two
| | 03:35 |
circumstances.
Either, when the user presses the device's
| | 03:39 |
back button or a back button that I'll
place back into the application.
| | 03:44 |
Let's start with the applications back button.
| | 03:47 |
In applications hosted in Honeycomb or
later, that is Android 3, the action bars
| | 03:52 |
launcher icon can be easily transformed
into a back button.
| | 03:58 |
And that's the preferred way to create a
back button in these latter versions of
| | 04:01 |
the operating system.
To do this, you just need to call a single
| | 04:06 |
line of code.
Go to the onCreate method, place the
| | 04:10 |
cursor after the call to set content view
and call this code
| | 04:14 |
getActionBar.setDisplayHomeAsUpenabled and
pass in a value of true.
| | 04:23 |
When you call that method, the launcher
icon is transformed into an options button
| | 04:27 |
and that automatically generated options
button will have an ID of home.
| | 04:34 |
So, now to handle the event that happens
when the user touches that button, we'll
| | 04:39 |
use the method on options item selected.
I'll go down to the bottom of the code,
| | 04:45 |
and I'll add in a new method. Onoptionsitemselected.
| | 04:51 |
This is an override so, I'll type in the
first part of the method name, Ctrl space
| | 04:56 |
and select it.
When the method is called, the selected
| | 05:00 |
menu item is passed in as an argument
named item and I'll use conditional code
| | 05:05 |
to check the item id.
of that item.
| | 05:09 |
Within an if statement, I'll use if
item.getItemId and I'll compare its value
| | 05:15 |
to this item id. Android.R.id.home.
| | 05:22 |
If those two values match, I'll call my
new method save and finish.
| | 05:27 |
And then either way, I'll return a value
of false, meaning I've handled this event,
| | 05:32 |
don't do anything else.
So, now let's test that much code to see
| | 05:37 |
if the back button appears.
I'll run the application in the emulator,
| | 05:43 |
and when it comes to life, I will touch
the item in the list and I'll see that the
| | 05:47 |
launcher icon has transformed successfully
into a back button.
| | 05:52 |
Now I'll add one other way to call this
function, and that's when the user touches
| | 05:56 |
the device's back button.
That triggers a method called
| | 06:00 |
onBackPressed, and I'll override that.
I'll type the beginning of the method name
| | 06:05 |
and select it, and instead of the super
class's version of the method, I'll call
| | 06:10 |
my save and finish method.
So, now regardless of whether the user
| | 06:15 |
touches the launch icon or the device is
back button, I'll be sending data back to
| | 06:19 |
the main activity.
Now, lets handle what happens when the
| | 06:23 |
main activity comes back to life.
From the main activity, I launched the
| | 06:29 |
editor by calling the method startActivityForResult.
| | 06:34 |
And I passed in this value 1001, that was
the request code.
| | 06:39 |
Now, I've used this value a couple of
times and to ensure consistency, I'll turn
| | 06:44 |
this into a constant.
I'll select one of the versions of 1001,
| | 06:49 |
then right click, and choose Refactor >
Extract Constant.
| | 06:55 |
And I'll set the name of the constant to
editor activity request.
| | 07:03 |
That creates the constant at the top of
the code but also changes the version
| | 07:06 |
here.
I'll copy that and then I'll paste it in
| | 07:10 |
here where I'm also using the same value.
Now, when the editor activity returns to
| | 07:16 |
the main activity, a method called
onActivityResult will be triggered.
| | 07:22 |
And as before, it's an override.
I'll type the beginning of the method
| | 07:26 |
name, press Ctrl+space and choose the
method, and then I'll get rid of the
| | 07:30 |
default implementation.
When this method is called, it's a good
| | 07:35 |
idea to make sure you're coming from the
activity you expect, and that you get the
| | 07:39 |
right result code.
These values are passed into the method as
| | 07:45 |
these arguments, requestCode and resultCode.
| | 07:49 |
So, within the method I'll create an if
statement and I'll set the condition to
| | 07:52 |
the following.
If the requestCode matches my constant,
| | 07:57 |
EDITOR_ACTIVITY_REQUEST and the resultCode
matches the constant, RESULT_OK.
| | 08:04 |
Then, I'm ready to take that data and save
it to persistent storage.
| | 08:12 |
First, I'll collect the data and put it
into a note object.
| | 08:16 |
I'll create a new note item that I'll call note.
| | 08:20 |
And I'll instantiate it with the note
arguments constructor.
| | 08:23 |
Then I'll set its data.
I'll call note.setKey, and I'll pass in
| | 08:29 |
the key that was passed back from the editor.
| | 08:34 |
Using this argument, the data argument
which is an instance of the intent class.
| | 08:39 |
This is the same intent object that was
passed back from the editor activity.
| | 08:45 |
I'll get the key value by calling
data.getStringExtra and I'll pass in key.
| | 08:51 |
And then I'll do the same thing for the
text value.
| | 08:54 |
Calling the notes's setText method and
passing in the data intent's
| | 08:58 |
getStringExtra method.
And passing in text.
| | 09:08 |
Now, I'm ready to save the data to
persistent storage.
| | 09:11 |
And to do that, I'll use the update method
of the data source class.
| | 09:15 |
I created this method a while back, and
all it does is to take a shared
| | 09:19 |
preferences editor, use a put string
method passing in the key and the text
| | 09:23 |
value, and commit the change.
I'll go back to the main activity, and
| | 09:30 |
I'll use one more line of code, a call to
my refreshDisplay method.
| | 09:36 |
And that means now that I've made changes
to my persistent storage, re-request the
| | 09:40 |
data for persistent storage and update the
display of the list.
| | 09:44 |
And now, I'll test the application completely.
| | 09:48 |
I'll run it in the emulator again and I'll
create a new note.
| | 09:53 |
I'll type in, get groceries.
And then I'll click the launcher icon, the
| | 09:57 |
back button and confirm that the data appears.
| | 10:02 |
And this time I'll click the updated note
and change it.
| | 10:08 |
And this time I'll click the device's back
button and confirm that that update works
| | 10:12 |
as well.
So, now I'm able to add and update notes.
| | 10:18 |
And the data is being saved to persistent storage.
| | 10:20 |
The functionality of my note taking app is
almost complete.
| | 10:25 |
I'll just need to add a delete feature,
that lets the user delete a note and the
| | 10:28 |
initial version of my app would be
complete.
| | 10:31 |
| | Collapse this transcript |
| Deleting notes| 00:00 |
The note taking app now has the ability to
add and update notes and now I want the
| | 00:04 |
user to be able to delete notes as well.
The user interface pattern for deleting
| | 00:11 |
items from a list varies from one app to
the next.
| | 00:15 |
Unlike other mobile operating systems,
there's no single required user interface
| | 00:19 |
for this operation but the most common one
you'll see, is the context menu.
| | 00:25 |
When the user clicks and holds on an item,
and then releases it.
| | 00:29 |
Instead of being registered as a click,
it's registered as a request for a menu.
| | 00:34 |
Then the menu can contain an option that
lets them delete the selected item.
| | 00:40 |
So that's how we'll implement it in our app.
| | 00:42 |
I'll do all of this work in the main
activity Java class.
| | 00:46 |
The first step is to take the list control
that's a part of our list activity and
| | 00:51 |
register it for context menus.
You do this by calling a method called
| | 00:57 |
register for context menu.
And you pass in the list view that's a
| | 01:02 |
part of the list activity.
I'll do this in the on create method, I'll
| | 01:06 |
look at my main activity class in
fullscreen mode.
| | 01:11 |
I'll place the cursor after said content
view, and I'll call the method register
| | 01:15 |
for context menu.
Then, I'll pass in the list view.
| | 01:21 |
Using another method called get list view.
So now when the user touches and holds on
| | 01:26 |
an item for a moment, then releases it,
it'll be seen as that context menu
| | 01:30 |
request.
And it'll result in calling a method
| | 01:34 |
called on create context menu.
Each time the method is called You can
| | 01:39 |
either load a menu that you define in XML,
or, if your menu is going to be variable
| | 01:43 |
depending on the circumstance, or, you're
only adding an item or two, you can do it
| | 01:48 |
all in Java code.
I'm going to use the pure Java code
| | 01:54 |
approach, because my context menu will
only contain a single item.
| | 01:58 |
Before I create the context menu I'm going
to set up a couple of more declarations at
| | 02:03 |
the top of the class.
First, I'm going to declare a field
| | 02:08 |
that'll be used as the ID of my context
menu item.
| | 02:14 |
I'll place the curser after my existing constant.
| | 02:17 |
I'll create another private static final
integer and I'll name this menu delete ID
| | 02:22 |
and I'll give it a value of 1002.
It can be any integer value you like.
| | 02:30 |
Just make sure you're not using a value
that's used elsewhere.
| | 02:32 |
Next I'll also create a field that I'll
call current note ID.
| | 02:38 |
Data typed as an integer.
There are going to be two methods.
| | 02:43 |
One to construct the context menu and one
to handle the event that's fired when the
| | 02:48 |
user selects a menu item.
You'll be able to detect which item in the
| | 02:53 |
list the user has selected when the
context menu is constructed but not when
| | 02:57 |
the menu item is selected.
So you have to save it persistently
| | 03:01 |
between the two operations.
And that's what this new field is for.
| | 03:07 |
I'll go down to the bottom of my existing code.
| | 03:10 |
And I'll add a new method.
This is an overwrite, and it's named on
| | 03:15 |
create context menu.
I'll create the method signature and
| | 03:20 |
remove its default implementation.
You receive 3 arguments in this method, a
| | 03:26 |
context menu, which is the menu that will
be displayed.
| | 03:30 |
A view and something called ContextMenuInfo.
| | 03:36 |
My first task is to figure out which task
in the list, that is which note, that the
| | 03:39 |
user wants to delete.
I can get that information from the
| | 03:44 |
ContextMenuInfo object but only if I
recast it to one of its sub-classes.
| | 03:51 |
So I'm going to create a variable that
I'll call adapter context menu info.
| | 03:56 |
And I'll name it info.
And I'll get that reference by simply
| | 04:00 |
casting menu info.
I'll type in that existing argument name.
| | 04:06 |
Then, I'll press command one, and I'll add
the casting.
| | 04:11 |
So now the menu info object has been cast
as info, and that object can tell me which
| | 04:16 |
item of the list I'm talking about.
On the next one, I'll get that information
| | 04:23 |
and save it to my current note ID field.
I use this code.
| | 04:29 |
currentNoteId equals info.id.
I have a problem with this code.
| | 04:34 |
The Id field of the info object is a long
value and current node Id needs to be an
| | 04:39 |
integer.
I'll explain why in a moment.
| | 04:45 |
So I'm just going to use casting syntax
here, and down cast from the long to the
| | 04:50 |
int.
So now, I've saved the information about
| | 04:54 |
which item I want to delete, and I'm ready
to add an item to the menu, and here's how
| | 04:59 |
I'll do it.
I'll use the menu argument that was passed
| | 05:03 |
into this method, and I'll call it add
method, and I'll pass in four arguments.
| | 05:09 |
The first argument is called a group id.
You only need a value there if you're
| | 05:15 |
going to have groups of menu items.
I'm not.
| | 05:18 |
I'm just going to have a single menu item.
So I'll pass in a dummy value of zero.
| | 05:24 |
Next, I'll pass in the ID constant that I
created earlier.
| | 05:28 |
Menu delete I.D.
and I'm saying that the menu item I'm
| | 05:33 |
adding will have this I.D.
next I'll pass in another integer which is
| | 05:40 |
the order in which I want the menu items
to be listed.
| | 05:44 |
Once again I only have one so I'll pass in
zero and finally I'll pass in a string.
| | 05:49 |
I'm asked for a character sequence but a
string will be automatically transformed
| | 05:53 |
as needed.
And this is the label that the user will
| | 05:57 |
see.
So now when the context menu appears,
| | 06:00 |
it'll have a single menu item, it'll say
delete, but it'll have this ID that I
| | 06:05 |
passed in.
Now when the user selects this menu item
| | 06:10 |
That'll trigger another method.
This one is called on context item
| | 06:15 |
selected.
Once again, it's an override.
| | 06:19 |
So I'll type in the beginning of the
method name and fill in the method
| | 06:23 |
signature.
I'll leave this return statement in.
| | 06:26 |
I'll need it in a moment.
And then, when the method is called, I'll
| | 06:30 |
compare the item ID of the item argument
that's being passed in here.
| | 06:37 |
To my menu delete ID constant that I use
to construct the menu item.
| | 06:41 |
I'll use an if clause, and I'll set the
condition as follows.
| | 06:47 |
Item dot get item ID, and I'll compare
that value to my constant.
| | 06:54 |
Menu to lead id.
If those two values match, I'll delete the
| | 06:58 |
item from persistent storage.
I'll get a reference to the selected note.
| | 07:05 |
I'll create a new note item reference, and
I'll get its value by calling my notes
| | 07:09 |
list's object's get method, and passing
the current note id.
| | 07:14 |
Then, I'll use my data source class's
remove method.
| | 07:19 |
I created this in the last chapter.
And I'll pass in the note object.
| | 07:27 |
And then just as I did when I updated
notes and saved them to persistent
| | 07:30 |
storage, I'll call refreshDisplay.
And that's all the code I need.
| | 07:36 |
And I'm ready to test.
I'll run the application in the emulator,
| | 07:41 |
and when it opens, I'll click and hold on
an item.
| | 07:46 |
The contents menu appears with the delete
menu item, I click it and the note is
| | 07:50 |
removed and the list is updated.
And so now all of the functionality of my
| | 07:55 |
note apps is in place.
I can add, update and delete notes and
| | 07:59 |
save and remove them in persistent storage.
| | 08:03 |
In the next chapter, I'll show you how to
make some changes to the app that will
| | 08:07 |
make it run and look just as good on older
versions of Android, as on the newer ones.
| | 08:13 |
| | Collapse this transcript |
|
|
6. Supporting Older Versions of AndroidGetting and integrating ActionBarSherlock| 00:00 |
The application now works well on the
newer versions of Android, starting with
| | 00:04 |
Android 3 or Honeycomb.
But before deploying the application, I'd
| | 00:09 |
like to make it compatible with older
versions, starting with Froyo, in
| | 00:13 |
developer terms that's API version 8.
So, I've opened a version of my eclipse
| | 00:19 |
project called older versions.
In this version of the project, I've done
| | 00:24 |
a little bit of code clean up.
I've removed unused imports, and I've also
| | 00:28 |
tuned my code a little bit using constants
instead of literal strings whenever I've
| | 00:33 |
referring to the key and the text values.
And also using string resources instead of
| | 00:40 |
literal strings.
Such as this one, r.string.delete in the
| | 00:45 |
context menu.
The only change I'll make directly to this
| | 00:49 |
project right now, is to make it usable on
the older versions of Android.
| | 00:54 |
I'll go to the application manifest.
If it opens in the visual interface, click
| | 01:00 |
on the XML view, and change the minimum
SDK version from 13 to 8.
| | 01:07 |
Save your changes.
And then, assuming that you have a virtual
| | 01:11 |
machine created with 2.3 or Gingerbread,
you can now test it.
| | 01:17 |
I'll run the application, and I'll choose
my Gingerbread emulator, and here it is.
| | 01:23 |
And when the application launches, the
Action bar isn't displayed.
| | 01:28 |
It does run, but because the Action bar
isn't a part of the older operating
| | 01:32 |
system, all you see is the app name.
Some of the functionality is still
| | 01:38 |
available.
For example, the plus icon that appears on
| | 01:42 |
the action bar on Jelly Bean is available
in the menu.
| | 01:47 |
But when I click it, the app crashes.
I'll go over to log cat and see what
| | 01:52 |
happened, and I'll see that it's looking
for the method Get Action Bar, which is
| | 01:57 |
not a part of Gingerbread.
So, you could write a whole bunch of
| | 02:02 |
custom code, and create alternate layouts
to solve this, but it turns out there's a
| | 02:07 |
much easier solution.
An Android developer named Jake Wharton
| | 02:12 |
has created a library called ActionBarSherlock.
| | 02:17 |
It's available from this website, actionbarsherlock.com.
| | 02:22 |
It's an extension of the Android support
library that lets you implement the action
| | 02:26 |
bar across all version of Android.
Before you continue with the coding,
| | 02:32 |
download this library in one of these
archive formats, and extract it.
| | 02:38 |
I've extracted it to my Desktop, but you
can place it anywhere on your hard disk.
| | 02:44 |
This is the folder that I extracted.
The critical sub-folder is this one,
| | 02:49 |
actionbarsherlock.
It's an Android project that you'll be
| | 02:54 |
able to import and link to your application.
| | 02:58 |
I'll go back to Eclipse, and I'll go to
the package explorer.
| | 03:03 |
And now I'm going to import action
actionbarsherlock into my workspace.
| | 03:09 |
I'll choose File > Import, and then under
the android category, I'll choose existing
| | 03:14 |
android code into workspace.
I'll click Next and then Browse.
| | 03:23 |
I'll go to my Desktop where I extracted
the Action Bar Sherlock files.
| | 03:27 |
I'll double-click, and I'll select the
ActionBarSherlock sub-folder, and click
| | 03:35 |
open.
Then to make sure that you have a copy of
| | 03:39 |
this project that's part of your project,
select Copy Project into Work Space and
| | 03:43 |
click Finish.
Here's the ActionBarSherlock folder, it's
| | 03:51 |
now in Eclipse project.
Working Jelly Bean, you'll get an error
| | 03:56 |
showing up in the consolel.
It says, unable to resolve target android
| | 04:01 |
14.
The issue here has to do with support
| | 04:04 |
library that's included in your project
and ActionBarSherlock project.
| | 04:11 |
It's part of your Libs folders, and it's
named android support V4.jar.
| | 04:18 |
There's a version of this jar file also in
ActionBarSherlock, but they don't match
| | 04:22 |
each other.
To fix this, take the version that's in
| | 04:26 |
your Libs folder, and copy and paste it
into the Libs folder of ActionBarSherlock,
| | 04:31 |
and overwrite the version that's included
in that library.
| | 04:37 |
That will clean up that error.
The two projects are now using the same
| | 04:42 |
version of the library, and that's critical.
| | 04:46 |
And here's one thing you can do to make it
easier to work with your project in the
| | 04:49 |
future.
Go to the project and go to its
| | 04:52 |
Properties, and go to the Project
References category, and select the
| | 04:58 |
project ActionBarSherlock.
Now, I'll close both projects, and then
| | 05:06 |
I'll double-click Older Versions to open it.
| | 05:11 |
Because this project now references the
ActionBarSherlock project, I'm prompted to
| | 05:17 |
open it.
I'll click Yes, and now I can open my code
| | 05:21 |
and start using the ActionBarSherlock
library to implement the action bar on the
| | 05:25 |
older versions of Android.
And I'll show you the code you need to
| | 05:31 |
change in the next movie.
| | 05:32 |
| | Collapse this transcript |
| Enabling the action bar on all versions of Android| 00:00 |
I'm about half way through the process of
implementing the action bar for older
| | 00:03 |
versions of Android.
This is the state of the application right
| | 00:07 |
now.
Showing the action bar on Jelly Bean.
| | 00:10 |
But only the app name on Gingerbread.
I'll go back to Eclipse where I've
| | 00:16 |
imported and linked the action bar short
lock library.
| | 00:19 |
And now I'm ready to start making some
code changes.
| | 00:22 |
I'll start in the main activity class.
ActionbarSherlock does its work by
| | 00:27 |
providing alternative versions of many of
the common Android classes.
| | 00:33 |
For example, if you want to use
Actionbarsherlock on a list activitiy.
| | 00:38 |
Instead, use a class called Sherlock ListActivity.
| | 00:43 |
I'll get rid of this super class
declaration, and I'll type sher and press
| | 00:47 |
Control + Space, and there's a list of all
of the alternative classes.
| | 00:53 |
And I'll choose this one, SherlockListActivity.
| | 00:55 |
That adds an import for that class, and I
no longer need the import for
| | 01:00 |
ListActivity.
So I'll delete it.
| | 01:05 |
You could also use the Organize Imports
feature from the Source menu.
| | 01:09 |
I'll save my changes, and then go and look
at my Problems View.
| | 01:14 |
I have two new errors in the Problems view.
| | 01:18 |
And they're the first clue to something
you need to do in you classes that use
| | 01:21 |
Sherlock.
I'm getting this error in 2 places, in
| | 01:26 |
method that use the menu and the menu item class.
| | 01:30 |
Here's what's going on.
Action by Sherlock provides versions of
| | 01:35 |
these classes as well.
And you need to make sure you're using
| | 01:39 |
those, and not the versions of the classes
that are a part of the Android SDK.
| | 01:45 |
To make this happen, I'll go back up to my
import statements, and I'm going to change
| | 01:49 |
the imports for menu and menu item, to use
the Action Bar Sherlock versions.
| | 01:55 |
I'll change the menu class first.
I'll get rid of Android.view as the
| | 02:01 |
classes package and replace it with com.actionbarsherlock.view.
| | 02:08 |
Now, I'll copy that and I'll paste it in
place with the menu item.
| | 02:13 |
I'll save those changes and now I have new errors.
| | 02:19 |
The next issue is in the onCreate options
menu method.
| | 02:23 |
The problem here is that I'm using a
method called get menu inflator that's a
| | 02:27 |
part of the activity but, instead I need
to use a get menu inflator method that's a
| | 02:32 |
part of sure luck.
The solution for this is to place the
| | 02:38 |
cursor before the call to get menu
inflator And call a method called get
| | 02:42 |
sherlock.
I'll type get S and press control, space
| | 02:48 |
and choose getSherlock and it returns the
action bar sherlock object.
| | 02:55 |
I'll separate those with a period, save my
changes and that error goes away.
| | 03:02 |
The next error is in the
onContextItemSelected method.
| | 03:06 |
This error appeared, when I replaced the
menu item Import up above.
| | 03:12 |
And that's because, onContextItemSelected,
expects the Android version of Menu Item,
| | 03:17 |
and not the Action Bar Sherlock version.
So to fix that, I'll add the package of
| | 03:23 |
the menu item class as an explicit
declaration with android.view.
| | 03:29 |
I'll save those changes.
Now I'll make the same sorts of changes to
| | 03:34 |
the not editor activity class.
The note editor activity currently extends
| | 03:39 |
the activity class and I'll change that to
Sherlock activity.
| | 03:44 |
Just as I did with the list activity, I'll
correct the imports.
| | 03:48 |
I pressed control space to add the
Sherlock activity class and then command
| | 03:53 |
shift O to organize the imports.
Or on Windows, Control + Shift + O.
| | 03:59 |
Next I'll make the same sort of changes to
the imports that I did before.
| | 04:05 |
I'll go back to main activity I'll scroll
to the top to my imports.
| | 04:11 |
I'll grab the import
com.actionbarsherlock.view, copy it, go
| | 04:16 |
back to the note editor, and replace the
menu item here.
| | 04:24 |
And that corrects the item here that's
looking for the menu item.
| | 04:29 |
Finally I need to change this call, getActionBar.
| | 04:33 |
This is actually a method that doesn't
even exist in older versions of Android.
| | 04:37 |
And you might get away with compiling the
application with it But when it runs it
| | 04:42 |
would crash.
Instead of Get Action bar, you can correct
| | 04:47 |
this issue with a method called Get
Support Action Bar.
| | 04:53 |
That's a method that's a part of the
Action Bar Sherlock Libary.
| | 04:57 |
I'll Save those changes.
I'll go back to my problems view, and see
| | 05:02 |
that all of the fatal error are gone.
I still have these warnings, but I can
| | 05:06 |
ignore those.
I have one more step to follow before I
| | 05:10 |
can test the application.
I'll go to the Android Manifest file.
| | 05:17 |
In this file, I'm declaring the theme
right here.
| | 05:20 |
And I'm using something called app theme.
When you use action bar sherlock you must
| | 05:26 |
themes that are provided as part of that library.
| | 05:30 |
I'll get rid of app theme and press
Control + Space type theme and there's a
| | 05:35 |
list of all the Sherlock theme's.
I'll use this one.
| | 05:40 |
Theme.sherlock.like.dark action bar.
These are declared in files in the
| | 05:46 |
Resources folder of the action bar
Sherlock Library.
| | 05:49 |
I'm ready to test the application.
I'll go back to my main activity and click
| | 05:55 |
the Run button.
And I'll choose the ginger bread emulator.
| | 05:59 |
When it opens it now looks exactly the
same as the version in jelly bean.
| | 06:07 |
I can click the plus icon, type in a note
and I see that the action bar appears here
| | 06:12 |
and because I've made the call to turn the
launcher icon into an up button I see the
| | 06:18 |
little back arrow graphic and I can click
and go back.
| | 06:26 |
And the application now works exactly the
same on all versions of Android.
| | 06:31 |
When you package your application for
deployment, be sure that ActionBarSherlock
| | 06:36 |
is included.
It's open source and completely free.
| | 06:40 |
And it makes it possible to make your
applications look the same Across all
| | 06:43 |
versions of Android.
| | 06:45 |
| | Collapse this transcript |
|
|
ConclusionNext steps| 00:00 |
Thanks for watching this course, Building
a Note-Taking App for Android.
| | 00:05 |
To learn more about Android App
Development, if you're getting started
| | 00:08 |
with Android for the first time, I
recommend watching Android App Development
| | 00:12 |
with Java Essential Training.
It's a comprehensive course that teaches
| | 00:18 |
you about the basic architecture of
Android apps and about many of the
| | 00:22 |
features of the Android API's.
To learn more about working with data on
| | 00:27 |
android devices, watch Android SDK: Local
Data Storage.
| | 00:32 |
In addition to more information about
shared preferences, this course teaches
| | 00:36 |
how to work with XML and JSON data files
and also how to work with SQL Lite.
| | 00:43 |
And we'll get building and monetizing game
apps for Android.
| | 00:46 |
To learn how to build a completely type of
app for Android devices, and at developing
| | 00:50 |
applications for Amazon Kindle devices,
for information about the API's that are
| | 00:54 |
specific to Kindle.
If you want to learn more about the Java
| | 00:59 |
programming language, you can get started
with Java with Java Essential Training or
| | 01:03 |
learn about advanced techniques with Java
Advanced Training.
| | 01:08 |
And to learn about other ways of putting
Java to work, you can watch Up and Running
| | 01:13 |
with Java Applications.
These courses, taken altogether, can help
| | 01:18 |
you learn more about working with the
Android SDK and programming with Java.
| | 01:23 |
| | Collapse this transcript |
|
|