Programing for beginners
Programing for beginners
beginners
Chapter 1
fManager.beginTransaction()
.upload(R.identityentification.detailFragmentHolder, frag)
.commit();
We can now run our app withinside the portrait orientation and notice the listing:
Tap the again button, rotate the tool to panorama, and faucet on V Putin to look our Fragments
displayed aspect via way of means of aspect:
Let's consider whilst we ought to use Fragments and whilst we should not via way of means of
searching at a few regularly requested questions.
FAQ
Hopefully, you've got got discovered sufficient on this bankruptcy to comprehend that the use of
Fragments similarly complements reusability and encapsulation of our code, and every time we
enforce some thing extra than only a unmarried, easy UI, it's miles properly really well worth the
overhead to apply Fragments.
Further remember that even the maximum easy of apps can evolve. If your easy unmarried-
display screen app for telephones best, all of sudden desires to be ported for drugs, you may want
to refactor the whole lot to apply Fragments. This is constantly more difficult than the use of
Fragments from the begin.
Probably, yes! Unless you've got got a very compelling case now no longer too. However, on
this ee-e book, to study new ideas, which include taking pictures an picturegraph on an Android
tool or showing the customers' region in Google maps, we can achieve this with out Fragments
getting withinside the manner of the brand new code.
Summary
Potentially, this become one of the maximum complex apps we've constructed. If it's miles in
any respect uncertain precisely what happened, the manner to triumph over that is to interrupt it
into portions (or fragments).
Each Fragment has a category and a format. The Fragment with the listing communicates with
the Activity thru the interface, and the Activity both hundreds a brand new (element) Fragment
into itself (whilst in panorama) or begins offevolved a brand new Activity that hundreds the
identical (element) Fragment whilst withinside the portrait orientation. All the statistics is tucked
away in our singleton and may be essentially forgotten approximately due to the fact it is able to
best ever be instantiated once, and it's miles assured that any elegance converting or analyzing
the statistics will achieve this from the identical example.
Certainly, there can be a few factors of the code or concepts from this bankruptcy that can be
nevertheless uncertain to you however with repeated use, you could lead them to like 2nd nature.
In the following bankruptcy, we aren't going to boom the complexity any similarly. So if a lot of
these Fragments and interfaces aren't definitely clean, it does not be counted. We will revisit
those standards one after the other over the direction of the relaxation of the ee-e book on the
identical time as we inspect extra approximately the Android API.
If you've got got ever desired to make one of these cool swiping UIs just like the Angry Birds
level-choice menu wherein you could swipe from display screen to display screen, then the
following bankruptcy is for you. And as you may assume, we can get a chunk extra acquainted
with Fragments whilst we're at it.
Paging is the act of shifting from web page to web page, and on Android, we do that via way of
means of swiping a finger throughout the display screen. The contemporary-day web page
transitions in a course and velocity to in shape the finger movement. It is a beneficial and
sensible manner to navigate round an app, however possibly even extra than this, it's miles a very
enjoyable visible impact for the person. Also, as with ListView, we are able to selectively load
simply the statistics required for the contemporary-day web page, and possibly the statistics for
the preceding and subsequent pages.
In the following screenshot, you could see the calendar app at the Nexus five emulator paging
among months. Be certain to release an emulator and supply it a attempt in case you are
uncertain how paging and swiping works:
In the following figure, we are able to see the well-known Angry Birds level-choice menu
displaying swiping/paging in motion:
The Android API, as you will have come to assume via way of means of now, has a few answers
thru which you could acquire paging in a pretty easy way.
Achieve paging and swiping with photographs like you may do in a picturegraph gallery app.
Implement paging and swiping with Fragments, a good way to supply our app the cappotential to
provide our customers the capacity to swipe their manner thru a choice of person interfaces. This
will supply our apps massive cappotential.
We will now no longer be including paging/swiping to the Where it is snap app, however allow's
construct paging mini apps: one with photographs and one with Fragments.
Chapter 2
Building an picturegraph gallery/slider app The first issue we ought to do is upload the six
photographs that we can have in our gallery to the drawable folder. But we need to do matters a
chunk otherwise right here. You can discover those photographs withinside the Chapter
20/Image Slider/drawable-xhdpi folder of the down load package. The following is a illustration
of those photographs: Create a brand new folder known as drawable-xhdpi withinside the res
folder via way of means of proper-clicking at the res folder and navigating to New | Android
useful resource listing.
Add the photographs to the folder which you simply created or, of direction, you can upload
extra exciting photographs, possibly a few pics you've got got taken.
The cause we do matters this manner is due to the manner some contemporary-day Android
gadgets cope with photographs. We already understand that during a perfect scenario, we ought
to offer photographs for the entire variety of various display screen densities and area them of
their suitable folders. To achieve this for this demonstration might be overkill;
in fact, relying upon the precise venture, it's miles occasionally overkill in a actual app as
properly.
It is due to the fact the producers of a few contemporary-day telephones need their gadgets to
appearance splendid, they lead them to routinely scale-up in length any photographs it thinks
may not already be excessive quality. The impact of that is that any photographs we area
withinside the everyday drawable folder are possibly to be supersized via way of means of those
gadgets with excessive-density monitors.
This frequently has the impact of inflicting the gadgets to expire of reminiscence and crash. By
putting the photographs withinside the drawable-xhdpi folder, we keep away from this trouble
due to the fact the tool assumes that the picturegraph does not want to be scaled up. Also,
gadgets with decrease density monitors will fortuitously use the photographs from the drawable-
xhdpi folder as properly.
For a easy picturegraph-paging app, we use the PagerAdapter elegance. We can think about this
to be like BaseApater, because it will cope with the show of an array of photographs in a
ViewPager widget. This is similar to how BaseAdapter handles the show of the contents of
ArrayList in ListView. All we want to do is override an appropriate strategies.
To enforce an picturegraph gallery with PagerAdapter, we first want ViewPager in our important
format. So you could see exactly what's required right here is the real XML code for
layout_main.xml. Edit layout_main.xml in order that it seems precisely like this:
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
android:identityentification="@+identityentification/pager"
android:layout_width="wrap_content"
view.ViewPager is the elegance that makes this capability to be had in Android variations that
have been launched earlier than ViewPager.
The identical way wherein we wanted a format to symbolize a listing object, we want a format to
symbolize an object; on this case, an picturegraph in our pager. Create a brand new format
document withinside the typical manner and make contact with it pager_item.xml. It can have a
unmarried ImageView widget with an ID of ImageView.
Use the visible fashion dressmaker to acquire this or reproduction the subsequent XML into
pager_item.xml: xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="10dp" >
[460]
Chapter 20
android:identityentification="@+identityentification/imageView
"
android:layout_width="match_parent"
Next, we want to enlarge PagerAdapter in order that it handles photographs. Create a brand new
elegance known as ImagePagerAdapter and make it enlarge PagerAdapter.
Add the subsequent imports to the pinnacle of the ImagePagerAdapter elegance. We generally
depend on the use of the shortcut Alt + Enter to feature imports. We are doing matters barely
otherwise this time due to the fact there are
some very in addition named training as a way to now no longer fit our objectives.
import android.widget.ImageView;
import android.widget.RelativeLayout;
Here is the elegance assertion with the extends... code delivered in addition to more than one
member variables. These variables are the Context item that we can placed to apply quickly and
an int array known as photographs. The cause for having an int array for photographs is due to
the fact we can
keep int identifiers for photographs. We see how this works in some code blocks time. The
ultimate member variable is LayoutInflater, which as you could in all likelihood wager can be
used to inflate every of the times of pager_item.xml.
int[] photographs;
LayoutInflater inflater;
[461]
Now, we want a constructor that units up ImagerPagerAdapter via way of means of receiving
Context from MainActivity in addition to the int array for the photographs and to initialize the
member variables with them.
Context context;
int[] photographs;
LayoutInflater inflater;
this.context = context;
this.photographs = photographs;
Now, we have to override the specified strategies of PagerAdapter. Immediately after the
preceding code, upload the overridden getCount technique, which truly returns the quantity of
picturegraph IDs withinside the array. This technique is used internally via way of means of the
elegance:
@Override
go back photographs.length;
}
Now, we have to override the isViewFromObject technique that simply returns boolean this is
based upon whether or not the contemporary-day View is the identical or related to the
contemporary-day Object this is exceeded in as a parameter.
Again, that is a technique this is used internally via way of means of the elegance. Immediately
after the preceding code, upload this overridden technique:
@Override
Now, we have to override the instantiateItem technique, and that is wherein we get maximum of
the paintings that issues us completed. First, we claim a brand new ImageView item after which
we initialize our LayoutInflater member. Next, we use LayoutInflater to claim and initialize a
brand new View from our pager_item.xml format document.
[462]
Chapter 20
After this, we get a connection with ImageView inner the pager_item.xml format. We can now
upload an appropriate picturegraph because the content material of ImageView is primarily
based totally on the placement parameter of the instantiateItem technique and an appropriate ID
from the photographs array.
Finally, we upload the format to PagerAdapter with addView and go back from the technique.
@Override
ImageView picturegraph;
inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
itemView.findViewById(R.identityentification.imageView);
container).addView(itemView);
go back itemView;
The ultimate technique we have to override is destroyItem, which the elegance can name whilst
it desires to eliminate the proper object primarily based totally at the price of the role parameter.
Add the destroyItem technique after the preceding code and earlier than the remaining curly
brace of the ImagePagerAdapter elegance:
@Override
[463]
As we noticed whilst coding ImagePagerAdapter, there's little or no to it. Just a case of nicely
imposing the instantiateItem technique and setting truthful overridden strategies that the
PagerAdapter elegance makes use of to assist make matters paintings easily at the back of the
scenes.
Finally, we are able to code our MainActivity elegance. As with the ImagePagerAdapter
elegance, for clarity, upload the subsequent import statements manually to the MainActivity.java
elegance earlier than the elegance assertion, as proven withinside the subsequent code snippet:
import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
Now, we want some member variables. Unsurprisingly, we want ViewPager, a good way to be
used to get a connection with ViewPager in our format, in addition to a ImagePagerAdapter
reference for the elegance that we've simply coded. We additionally want an int array to keep an
array of picturegraph IDs:
ViewPager viewPager;
PagerAdapter adapter;
int[] photographs;
@Override
...
All the relaxation of the code is going in onCreate. We initialize our int array with every of the
photographs that we delivered to the drawable-xhdpi folder.
We initialize ViewPager withinside the typical manner with the findViewByID technique. We
additionally initialize ImagePagerAdapter via way of means of passing in a connection with
MainActivity and the photographs array, as required via way of means of the constructor that we
coded formerly.
[464]
Chapter 20
Add the highlighted code withinside the onCreate technique:
@Override
setContentView(R.format.activity_main);
reference the photographs and placed them in our array photographs = new int[] {
R.drawable.image1, R.drawable.image2,
R.drawable.image3,
R.drawable.image4,
R.drawable.image5, R.drawable.image6 };
get a connection with the ViewPager withinside the format viewPager = (ViewPager)
viewPager.setAdapter(adapter);
Run the app withinside the typical manner on both the emulator or a actual tool. Using a actual
tool rather than the emulator can be extra enjoyable due to the fact you may be capable of use a
actual swiping movement together along with
In this screenshot, we are able to see the primary picturegraph from our int array:
Swipe a touch to the proper-hand aspect and left-hand aspect to look the easy captivating way
wherein the photographs transition:
Now, we can construct an app with nearly same capability besides that every web page
withinside the pager can be a Fragment, that may have any or all the capability that a everyday
Fragment may have due to the fact they may be everyday Fragments.
We can placed whole Fragments as pages in PagerAdapter. This is pretty effective due to the fact
as we understand, a Fragment may have loads of capability, even a complete-fledged UI.
To hold the code brief and truthful, we can upload a unmarried TextView to every Fragment
format, simply to illustrate that the pager is operating. When we see how smooth it's miles to get
a connection with TextView, however, it ought to be clean as to how we should effortlessly
upload any format that we've
discovered approximately up to now after which allow the person have interaction with it.
The first issue we can do is construct the content material for the slider. In this case, of direction,
the content material is Fragment. We will construct one easy elegance known as SimpleFragment
and one sincerely easy format known as fragment_layout.
This means that every slide can be same in look, however we can use the Fragment ID exceeded
in via way of means of FragmentManager on the instantiation because the textual content for the
one and best TextView. This manner, whilst we flip/swipe thru Fragments, it will likely be clean
that every Fragment is a brand new awesome example.
[466]
Chapter 20
When we see the code that hundreds Fragments from a listing, it will likely be easy to layout
absolutely exceptional Fragment training, as we've completed earlier than, and use those
exceptional training for a few or all of the slides. Each of those training should, of direction,
additionally use a exceptional format as properly.
As with the Image Slider app, it isn't truthful precisely which training want to be autoimported
via way of means of Android Studio. We use the training that we do due to the fact they may be
all well matched with every different and it's miles viable that in case you allow Android Studio
recommend which training to import, Android Studio gets it 'incorrect'. The venture documents
are withinside the Chapter 20/Fragment Pager folder.
Create a brand new venture known as Fragment Slider and depart all of the settings on the
default values.
Now, create a brand new elegance known as SimpleFragment, make it enlarge Fragment, and
upload the import statements
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
Holds the fragment identityentification exceeded in whilst created public static very last String
MESSAGE = "";
We ought to upload strategies. The first of that is newInstance, which we can name from
MainActivity to installation and go back a connection with Fragment. The subsequent code does
what we've visible earlier than. It creates a brand new example of the elegance, however it
additionally places a String into the Bundle item as a way to subsequently be study from the
onCreate technique. The String this is delivered to Bundle is that that is exceeded withinside the
one-and-best parameter of this newInstance technique.
Our newInstance technique which we name to make a brand new Fragment public static
SimpleFragment newInstance(String message)
[467]
go back fragment;
In the very last technique for our SimpleFragment elegance, we want to override onCreateView,
wherein, as typical, we can get a connection with the format that become exceeded in, and cargo
up fragment_layout because the format.
Then, the primary line of code unpacks the String from Bundle the use of getArguments.
@Override
..
Let's additionally make a high-quality easy format for Fragment, a good way to, of direction,
incorporate TextView that we've simply been the use of.
fragment_layout
format and click on on OK. Now, upload a unmarried TextView and set its identityentification
assets to textView.
We can now code the MainActivity elegance that handles FragmentPager and brings our
SimpleFragment times to existence.
This elegance includes important components. First, the adjustments we can make to the
overridden onCreate technique, and 2nd, the implementation of our internal elegance and its
overridden strategies of
FragmentPagerAdapter.
To code this elegance, we first upload the subsequent imports and a unmarried member variable
as a way to be the example of our implementation of FragmentPagerAdapter and
SimpleFragmentPagerAdapter:
import java.util.ArrayList;
import java.util.List;
SimpleFragmentPagerAdapter pageAdapter;
@Override
setContentView(R.format.activity_main);
[469]
Next, withinside the onCreate technique, we create a List for Fragments after which create and
upload 3 times of SimpleFragment, passing in a numerical identifier this is to be packed away in
Bundle.
We get a connection with ViewPager with findViewByID and bind our adapter to it with
setAdapter.
@Override
setContentView(R.format.activity_main);
fragmentList.upload(SimpleFragment.newInstance("1"));
fragmentList.upload(SimpleFragment.newInstance("2"));
fragmentList.upload(SimpleFragment.newInstance("3"));
Then, we override the getItem and getCount strategies, which can be used internally withinside
the identical manner as we used them withinside the ultimate venture, besides this time, we use
the strategies of List rather than the dimensions of the array.
Add the subsequent internal elegance that we simply mentioned to the MainActivity elegance:
[470]
Chapter 20
A constructor to acquire a fraction supervisor and a List public
SimpleFragmentPagerAdapter(FragmentManager fm, List fragments) {
of this constructor
high-quality(fm);
this.fragments = fragments;
@Override
go back this.fragments.get(role);
@Override
go back this.fragments.length();
Implement the activity_main format via way of means of copying the subsequent code. It
includes a unmarried widget, ViewPager, and it's miles essential that it's miles from the
android.support.v4.view hierarchy in order that it's miles well matched with the alternative
training that we use on this venture.
Amend the code withinside the layout_main.xml document that we simply mentioned:
xmlns:tools="http://schemas.android.com/tools"
android:layout_ width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/ activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
[471]
android:identityentification="@+identityentification/pager"
android:layout_width="wrap_content"
Run the app and you could swipe your manner, to the left or the proper, thru the Fragments
withinside the slider. The subsequent picturegraph indicates the visible impact produced via way
of means of FragmentPagerAdapter whilst the person attempts to swipe past the very last
Fragment in List: In this bankruptcy, we noticed that we are able to use pagers for easy
picturegraph galleries or to swipe thru complicated pages of a whole UI; however, we validated
this with a totally easy TextView.
In the following bankruptcy, we can examine some other sincerely cool UI detail this is utilized
in a few of the state-of-the-art Android apps, in all likelihood as it seems splendid and is a actual
pleasure, in addition to extraordinarily sensible to apply. Let's test
NavigationDrawer.
In this bankruptcy, we can begin the Where it is snap venture, and we can speak extra
approximately the functions that it'll have later. The venture can be mentioned proper up until
Chapter 27, Going Local – Hola! wherein it's miles finished, however we may not best be
operating in this app.
Where it is snap will characteristic a navigation drawer as a way of permitting the customers to
get entry to the functions and monitors of the app, and this could be the principle attention of this
bankruptcy.
Look on the functions of the Where it is snap venture Get began out at the Where it is snap
venture, which includes imposing its navigation drawer
[473]
What's so splendid approximately navigation drawer. Well, the primary issue that would trap
your eye is that it is able to be made to appearance extraordinarily stylish. Take a examine this
subsequent figure , which indicates off a navigation drawer in motion withinside the Google Play
app:
To be honest, proper from the begin, our navigation drawer isn't going to be as fancy as the only
withinside the Google Play app. However, the identical capability can be found in our app.
What else is neat approximately the navigation drawer is the manner that it slides to hide/monitor
itself whilst required. It is due to this conduct that it is able to be of a sizeable length, making it
extraordinarily bendy with reference to the alternatives that may be placed on it. When the
person is completed with it, it absolutely disappears like a drawer.
I recommend which you open up the Google Play app now and notice the way it works, if you
have not already.
You can slide your thumb/finger from the left-hand aspect fringe of the display screen and the
drawer will slowly slide out.
You can, of direction, slide it away once more withinside the contrary course.
[474]
Chapter 21
While the navigation drawer is open, the relaxation of the display screen is barely dimmed, as
visible the preceding figure, supporting the customers to attention at the navigation alternatives
provided.
You also can faucet everywhere off of the navigation drawer whilst it's miles open, and it'll slide
itself away, leaving the whole display screen clean for the relaxation of the app.
The drawer is likewise opened via way of means of tapping at the menu icon withinside the
pinnacle-left nook, as highlighted withinside the subsequent screenshot:
We also can tweak and refine the conduct of the navigation drawer, as we can see towards the
stop of the bankruptcy, via way of means of overriding some extra lifecycle strategies which are
known as at simply the proper time.
onConfigurationChanged strategies. Let's see what we can do with our Where it is snap app, after
which, we are able to get on with imposing a navigation drawer.
Where it is snap can be our maximum-superior app! It can have the subsequent functions:
It will provide the opportunity of a listing of tags, which whilst clicked takes you to a listing of
titles with that matching tag.
It will permit the person to take pics with the tool digital digicam and assign a identify in
addition to associated tags.
All of the statistics required (titles and tags) can be saved in a database. You will find out about
databases in Chapter 23, Using SQLite Databases in Our Apps, and we can upload a database
capability to Where it is snap in Chapter 24, Adding a Database to Where It's Snap.
[475]
When the person faucets on a picturegraph's identify in a listing, he/she can be able to see that
picturegraph and additionally be provided the choice of displaying a Google map of the region
the picturegraph become taken at.
We may even see the way to make this app multilingual (Spanish and English). Hola!
As with the Note To Self app, we can do matters as successfully as viable and use string assets
and Android naming conventions in our code.
We will construct this app over the direction of the following six chapters. As we discover and
exercise new functions of the Android API, we can then make use of them via way of means of
enhancing or including functions to Where it is snap.
The first issue we can do is put together the venture's assets and enforce a navigation drawer.
This can be the essential a part of the UI for this venture.
The venture documents that constitute a runnable model of this app, as it's miles on the stop of
this bankruptcy, may be located withinside the down load package withinside the Chapter
21/Where its snap 1 folder.
Create a brand new venture known as Where Its Snap and be given all of the default settings as
typical.
To cope with Marshmallow runtime permissions, as mentioned in Chapter 11, Widget Mania
withinside the Android permissions and marshmallows, we want to set the target API to 22.
To do that, select Android from the drop-down listing on the pinnacle of the venture explorer.
Now, double-click on at the construct.gradle (module: app) alternative this is close to the lowest
of the venture explorer window.
Change the highlighted line of code to make certain that targetSdkVersion is ready to 22, as
proven withinside the following code snippet:
defaultConfig {
applicationId "com.gamecodeschool.whereitssnap"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
Now, we are able to upload the assets that we can want withinside the subsequent six chapters.
[476]
Chapter 21
Preparing the assets
In this segment, we can put together the String assets. For this, open up the strings. xml
document from the res folder. We will now no longer want to return back again to this document
for
the whole venture. Some of the assets would possibly appearance a touch abnormal and certainly
won't be used proper away, however in case you appearance again on the functions of the
venture, it will likely be pretty smooth to wager wherein those String assets will subsequently be
used. We will, however, create some other strings.xml document in Chapter 27, Going Local –
Hola! whilst we make our app multilingual.
As properly as a few everyday String assets, there's a string-array detail with the call assets set to
nav_drawer_items. We will quickly see how in our Java code we are able to use this much like a
everyday Java array, just like the ones we mentioned in Chapter 13, Handling and Displaying
Arrays of Data.
Modify the contents of the strings.xml document in order that they may be similar to the
following code: Where It's Snap!
Settings
Tag 1
Tag 2
Tag 3
We at the moment are almost prepared to enforce our navigation drawer. Before we do, allow's
upload a few empty placeholder Fragments that we are able to use for every of the alternatives of
the drawer.
As we understand from our plan, there are 4 Fragments: picturegraph seize, identify listing, tag
listing, and displaying a image.
The first 3 are at once on hand from the principle navigation drawer UI. For those 3 Fragments,
we can quick create placeholder training and layouts in order that we are able to get
MainActivity stressed out up. Then, over the approaching chapters, we can upload the actual
capability and layouts.
Two of those 3 Fragments (titles view and tags view) can be a listing of clickable alternatives,
and so, the use of ListFragment looks as if a great choice. The third (the picturegraph seize view)
can be a good deal extra like a everyday format; so, Fragment is the high-quality choice.
Create a brand new elegance and make contact with it TitlesFragment. Amend the code in order
that it seems precisely just like the subsequent code, wherein we enlarge ListFragment and
enforce a primary onCreate technique prepared withinside the venture for later use:
@Override
Now, for the tags listing view, create a brand new elegance and make contact with it
TagsFragment. Amend the code in order that it seems precisely just like the subsequent code,
wherein we enlarge ListFragment and enforce a primary onCreate technique that is prepared for
later use withinside the venture: public elegance TagsFragment extends ListFragment {
@Override
[478]
Chapter 21
}
Now, for the Fragment as a way to subsequently permit the person to take a picturegraph in
addition to upload a identify and tags to it.
Create a brand new elegance and make contact with it CaptureFragment. Amend the code in
order that it seems precisely just like the subsequent code, wherein we enlarge
Fragment and enforce a primary model of onCreate and onCreateView prepared for later use
withinside the venture.
Here is the code for CaptureFragment.java: public elegance CaptureFragment extends Fragment{
@Override
savedInstanceState)fantastic.onCreate(savedInstanceState);
@Override
//Inflate the format document then get all essential references View view = inflater.inflate
Right-click on at the format folder and navigate to New | Layout useful resource document.
Name it fragment_capture and click on on OK.
[479]
Finally, drag a unmarried TextView onto the format and set its textual content assets to Capture.
We can now write code in MainActivity.java to deliver those Fragments to existence. However,
they may be presently simply clean, aside from the unmarried TextView that we simply
delivered to fragment_capture.xml.
Let's upload a sincerely easy, however definitely new, format as a way to outline the advent of
our app. Unsurprisingly, the format can have our navigation drawer in it.
The code for the format that follows in a second seems lengthy and complex, however on near
inspection, it's miles simply DrawerLayout inside a everyday RelativeLayout. Then, inside
DrawerLayout is RelativeLayout that has an identityentification of fragmentHolder. This
RelativeLayout is wherein we can switch our diverse Fragments inside and out. Then,
nevertheless inside DrawerLayout, we've ListView. It is this ListView as a way to keep all of the
alternatives of navigation drawer.
We will see precisely how we use this identityentification assets to make it come to existence
(slide inside and out) quickly.
Also, be aware that we set the width assets of ListView to 200dp. Feel unfastened to play with
this and make it wider or narrower as you like.
As neither of the preceding UI elements (RelativeLayout and ListView) had been given any
relative format commands, they'll each begin withinside the pinnacle-left nook and fill the whole
display screen, with the exception that ListView will best be 200dp wide. Also, due to the fact
ListView is asserted after RelativeLayout, a good way to keep our Fragments, it will likely be at
the pinnacle. This is precisely what we want.
Here is the code for activity_main.xml that we simply mentioned. Edit activity_ important.xml in
order that it seems precisely like this:
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"> xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:identityentification="@+identityentification/drawerLay out"
android:layout_width="match_parent"
[480]
Chapter 21
android:layout_height="match_parent"> android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:heritage="#ffffffff"
android:identityentification="@+identityentification/fragmentH
older">
android:identityentification="@+identityentification/navList"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="left|begin"
As with a few of the documents on this venture, it'll evolve as we progress. The following code is
the minimal requirement to get the navigation drawer operating and cargo up our Fragments.
First, we want to feature a few imports, and those want to be simply the proper training and as
with our paging apps withinside the ultimate bankruptcy, Android Studio does not constantly
recommend the high-quality elegance to import.
[481]
Navigation Drawer and Where It's Snap
ActionBarDrawerToggle: This allows us to deliver the menu icon withinside the motion bar to
existence and have interaction with DrawerLayout to open and near it. We will achieve this via
way of means of calling its strategies, and ActionBarDrawerToggle will cope with all of the
complexity in addition to offer a neat animation at the menu icon.
Add the imports and member variables that we simply mentioned thru this code snippet:
bundle com.gamecodeschool.whereitssnap1;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
@Override
setContentView(R.format.activity_main);
[482]
Chapter 21
...
...
We at the moment are in a role to consider the way to cope with Fragments. As we're managing
increasingly more numerous variety of Fragments, allow's create a technique that we are able to
name to in particular cope with switching among Fragments.
Next, proper after onCreate, we can upload a technique known as switchFragment as a way to
cope with switching among our Fragments whilst the person faucets on an alternative withinside
the navigation drawer UI.
Then, we initialize a String known as fragmentID as an empty string. We will use this identical
null Fragment item and empty String irrespective of which navigation alternative the person
chooses. What will vary, however, is how we initialize it.
The initialization is dealt with the use of transfer and role because the argument. We have 3 case
statements: 0, 1, and 2.
For every case, we initialize fragment with an appropriate kind of the Fragment elegance and set
the fragmentID String to a in addition suitable price, as we can quickly want so that you can hit
upon the presently displayed Fragment.
Note additionally that for TitlesFragment, we additionally create Bundle. At present, Bundle has
no characteristic. We upload it right here in order that we do not want to amend this technique
later. It will subsequently byskip withinside the tag that a person has clicked on so that you can
assist TitlesFragment display the proper listing of associated titles.
Add the primary a part of the switchFragment technique that we simply mentioned:
transfer (role) {
case 0:
fragmentID = "TITLES";
[483]
fragment.setArguments(args);
spoil;
case 1:
fragmentID = "TAGS";
spoil;
case 2:
fragmentID = "CAPTURE";
spoil;
default:
spoil;
In the following block of code, which completes the technique we began out withinside the
preceding block, we create a brand new FragmentManager as typical. After this, we name
beginTransaction this is chained with the update technique, which handles the destruction of the
prevailing Fragment, on the identical time as the use of our newly initialized Fragment and ID,
held in fragment and fragmentID respectively.
The ultimate line of code will close the drawer so that you can absolutely monitor the newly
decided on alternative/Fragment.
Add the highlighted code to the switchFragment technique on the factor indicated via way of
means of the remark this is highlighted withinside the following code: personal void
switchFragment(int role) {
...
[484]
Chapter 21
Close the drawer
mDrawerLayout.closeDrawer(mNavDrawerList);
Next, we can create a unmarried technique as a way to do the whole lot to definitely installation a
navigation drawer. The technique is known as setupDrawer, and we can write code to name it
from onCreate quickly.
Here is the way it works. We initialize mDrawerToggle on the identical time as we create a
brand new ActionBarDrawerToggle reference.
The onDrawerOpened technique first calls the discern technique after which units the identify of
the motion bar.
When the drawer is open, we need to inspire the person to make a choice. We achieve this via
way of means of placing the identify as Make choice. Finally, on this technique, the decision to
invalidateOptionsMenu reasons the motion bar to be redrawn.
In the onDrawerClosed technique, we once more begin via way of means of calling the discern
technique. Again, we set the identify of the motion bar, however this time, we use the
mActivityTitle String, and we can see precisely how that is configured withinside the onCreate
technique later on this bankruptcy.
The ultimate strains on this elegance are known as whilst the example is created and units up
mDrawerToggle after which passes it in setDrawerListener, which has the combined impact of
animating the menu button at the left-hand aspect of the motion bar because the drawer is
toggled among open and closed.
The following screenshot indicates the drawer toggle whilst the drawer is closed:
[485]
This subsequent screenshot indicates the drawer toggle whilst the drawer is open:
We can be capable of see this for actual close to the stop of this bankruptcy, which includes how
a neat animation morphs among the previous highlighted states.
Add the setupDrawer technique that we simply mentioned proper after the switchFragment
technique in MainActivity.java: personal void setupDrawer() {
invalidateOptionsMenu();
high-quality.onDrawerClosed(view);
invalidateOptionsMenu();
[486]
Chapter 21
};
mDrawerToggle.setDrawerIndicatorEnabled(genuine);
mDrawerLayout.setDrawerListener(mDrawerToggle);
We have now no longer visible onPostCreate or onConfigurationChanged earlier than, and there
aren't that many conditions wherein we want to apply them.
As the names suggests, they may be known as after onCreate and after a configuration extrade of
the Activity, respectively.
We use them right here in order that if the utility is going into the heritage or if the tool receives
rotated, the app will use onPostCreate and onConfigurationChanged to make certain that it
recollects the nation of the drawer and the toggle, and maintains them each in sync.
@Override
@Override
There are simply extra regions to take note of earlier than we are able to flip our interest to
onCreate and get all this code operating.
The onBackPressed technique is an overridden technique this is known as whilst the again button
is pressed. It is beneficial to use this technique to feature a capability due to the fact we are able
to make the app behave a touch extra because the person would possibly assume.
[487]
The first if assertion detects whether or not the drawer is open, and if it's miles, it closes it.
If you're on the house display screen of an app and also you faucet at the again button, you in all
likelihood assume it to quit. If you're on the second one display screen of an app and also you
faucet at the again button, you in all likelihood assume to move again to the primary display
screen.
The else block achieves this via way of means of growing a temporary Fragment reference, f,
and the use of the f instanceof TitleFragment circumstance, which returns genuine if
TitlesFragment is presently the kind in fragmentHolder. As the identify's display screen is
efficiently our domestic display screen, whilst this circumstance is genuine the app quits via way
of means of calling end, accompanied via way of means of System.exit(0).
If, on the alternative hand, every other Fragment is present, then we are able to anticipate that the
person desires to move again a display screen, so we name our switchFragment technique with 0
because the argument to load TitlesFragment.
@Override
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawer(mNavDrawerList);
}else {
getFragmentManager().
System.exit(0);
}else{
switchFragment(0);
[488]
Chapter 21
Now, upload the highlighted code to the
onOptionsItemSelected technique, a good way to make certain that our drawer toggle is dealt
with successfully on every occasion it's miles pressed:
@Override
//noinspection SimplifiableIfStatement
if (identityentification == R.identityentification.action_settings) {
go back genuine;
go back high-quality.onOptionsItemSelected(object);
Finally, in onCreate, we are able to placed all of the different portions of our code collectively.
First, we get a connection with ListView via way of means of calling findViewByID. Then, we
get a connection with DrawerLayout withinside the identical manner.
Next, we use the getTitle().toString() technique and assign the end result to mActivityTitle. The
impact of that is that the identify of our app is now held in
mActivityTitle.
Add the primary a part of the brand new code that we simply mentioned, as highlighted,
withinside the onCreate technique:
@Override
mNavDrawerList =
(ListView)findViewById(R.identityentification.navList);
[489]
mDrawerLayout =
Now, we can talk the ultimate a part of the code that is going withinside the onCreate technique
from wherein we simply left it.
We create a String array via way of means of calling getResources.getStringArray and passing
withinside the call of our array withinside the strings.xml document.
After this, we initialize ArrayAdapter (with the preceding array) and set it because the adapter
for ListView.
Lastly, we create an nameless elegance to deal with clicks on ListView, and we truly name
switchFragment with an appropriate role (whichItem) that become clicked.
Add the highlighted code that we mentioned simply after the code that we delivered formerly
into the onCreate technique:
@Override
...
navMenuTitles = getResources().
getStringArray(R.array.nav_drawer_items);
[490]
Chapter 21
mNavDrawerList.setAdapter(mAdapter);
setupDrawer();
getSupportActionBar().setDisplayHomeAsUpEnabled(genuine);
getSupportActionBar().setHomeButtonEnabled(genuine);
mNavDrawerList.setOnItemClickListener
(new AdapterView.OnItemClickListener() {
@Override
switchFragment(whichItem);
});
switchFragment(0);
That's it for our navigation drawer, and we are able to run the venture up to now. Now, we are
able to see the loading statistics animation supplied via way of means of default in ListView
from
[491]
When we drag from the left-hand fringe of the display screen, the drawer slides open:
Notice the conduct of the drawer whilst the again secret's pressed. This is due to the code that we
delivered in onBackPressed. You also can swipe the drawer away or faucet/click on at the left-
pointing arrow withinside the motion bar.
Note that in case you faucet on Capture withinside the navigation drawer, you may see the
unmarried TextView with the word "Capture" from the fragment_capture format, indicating that
our Fragments are certainly switching themselves round as intended.
Summary
Now, we've a operating Activity that fortuitously swaps exceptional Fragments inside and out of
RelativeLayout with an
[492]
Capturing Images
In this bankruptcy, we can see how we are able to harness the Android Intent elegance to feature
the in any other case complex capability with ease. Although that is a brief bankruptcy, it's miles
unexpected how a good deal we are able to get completed in those few pages. We will now no
longer best construct a totally short mini app with the picturegraph seize capability, however we
can additionally upload this capability to the Where it is snap app. At the identical time, we can
see how Android shops photographs which are captured via way of means of the digital digicam
and the way we have interaction with them. In this bankruptcy, we can: Look at the way to seize
an picturegraph from a digital digicam with the Intent elegance
Capturing photographs the use of the digital digicam Android presents approaches to jot down
apps that use a digital digicam:
One manner is to jot down a digital digicam app from scratch and make use of any or all the
functions of any digital digicam that the tool might also additionally have. This is a massive
subject matter and is normally best used whilst the app is designed to feature a few form of a
brand new digital digicam capability.
The different manner is to apply the prevailing digital digicam app to do the paintings for us.
We can be cheating (in a great manner) via way of means of the use of the prevailing digital
digicam app of the tool (alternative 2). We can do that the use of the Intent elegance that we first
noticed in Chapter 15, Android Intent and Persistence.
By cautiously building the argument exceeded into the constructor of the Intent elegance, we are
able to get different
apps to do paintings for us. We will see the code to seize an picturegraph, however the identical
easy strategies may be used to ship an e-mail, submit a message on social media platforms, play
media, and plenty extra except this.
[493]
Capturing Images
To have an Intent elegance release the digital digicam app, we can construct an Intent elegance
with
android.provider.MediaStore.ACTION_IMAGE_CAPTURE.
All we want to do is assemble an Intent elegance like this: Intent intent = new
Intent(android.provider.
MediaStore.ACTION_IMAGE_CAPTURE);
After we've completed this, we begin an Activity the use of our new Intent item, however in
contrast to in Chapter 15, Android Intent and Persistence, wherein we known as startActivity,
this time we name startActivityForResult in order that the brand new Activity is aware of we
need a end result (a few statistics) surpassed again to our Activity.
When we come to code the picturegraph seize capability of the Where it is snap app, we can take
matters even similarly.
Create a brand new venture and make contact with it Simple Photo. You can depart all of the
settings at their defaults as typical.
To cope with Marshmallow runtime permissions, as mentioned in Chapter 11, Widget Mania
withinside the Android permissions and Marshmallows segment, we want to set the target API to
22.
To do that, select Android from the drop-down listing on the pinnacle of the venture explorer.
Now, double-click on at the construct.gradle (module: app) alternative from the lowest of the
venture explorer window.
[494]
Chapter 22
Change the highlighted line of code in order that targetSdkVersion is ready to 22, as proven
withinside the following code:
defaultConfig {
applicationId "com.gamecodeschool.simplephoto"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
Now, we want to invite for the customers' permission to apply the digital digicam.
Adding the digital digicam permission to the manifest The first issue we want to do is edit the
AndroidManifest.xml document. The cause for that is that we want to invite the customers'
permission to get entry to their digital digicam.
Fortunately, including the digital digicam permission and characteristic is smooth. Open the
AndroidManifest.xml document from the manifests folder withinside the venture explorer. Add
the highlighted strains proven withinside the subsequent code:
model="1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
"android.intent.class.LAUNCHER" />
[495]
Capturing Images
This format is sincerely primary. When we upload the image seize capability into Where it is
snap later this bankruptcy, we can spend a chunk extra effort and time laying out the seize
Fragment:
identityentification="@+identityentification/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
[496]
Chapter 22
Coding the MainActivity elegance
First, we want to feature member variables: We have very last int known as
CAMERA_REQUEST. When we begin a brand new Activity and assume a few statistics again,
we have to ship an ID for the request. It is right exercise to apply a very last variable due to the
fact whilst we acquire statistics in onActivityResult, we want to be sure that it's miles the digital
digicam statistics that we are managing. Any time we name startActivityForResult, the respond
comes again to onActivityResult. We will see how we are able to confirm that we're definitely
managing the statistics we assume we're. In this easy app, it's miles a foregone end that we can
be receiving statistics from the digital digicam app, however as our apps get extra complicated,
this could now no longer constantly be the case.
personal static very last int CAMERA_REQUEST = 123; personal ImageView imageView;
@Override
setContentView(R.format.activity_main);
Next, withinside the onCreate technique, we get a connection with ImageView and Button in our
format.
Then, we code an nameless elegance to concentrate for clicks on Button. Note that the onClick
technique creates the brand new Intent elegance, which we mentioned in advance, as properly as
calls startActivityForResult and passes withinside the Intent elegance along side our
identityentification assets, CAMERA_REQUEST.
Now, upload the code that we simply mentioned to the onCreate technique. It is highlighted on
this subsequent code listing:
@Override
setContentView(R.format.activity_main);
imageView =
this.findViewById(R.identityentification.button1);
[497]
Capturing Images
photoButton.setOnClickListener(new View.OnClickListener() {
@Override
(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
});
Finally, we are able to upload the all-essential onActivityResult technique that captures the end
result (a picturegraph) from the Intent elegance, that is exceeded in as a parameter. Notice the int
requestCode parameter right here, this ought to in shape the identityentification assets that we
sent into startActivityForResult. Also, notice resultCode, which is likewise int.
We use an if assertion to check for 2 matters: Is this the statistics that we assume it's miles
(requestCode ==
CAMERA_REQUEST)?
Is there definitely a few suitable statistics in any respect in the Intent elegance (resultCode ==
RESULT_OK)?
It is viable that the Activity failed; it's also viable that the customers modified their thoughts and
did now no longer take a image. The if assertion handles those possibilities.
If all is properly, the execution enters the frame of the if assertion and we claim and initialize a
brand new Bitmap from the Intent elegance after which use the setImageBitmap technique to
show it on ImageView.
Add the onActivityResult technique that we simply mentioned: included void onActivityResult
(int requestCode, int resultCode, Intent statistics) {
RESULT_OK) {
statistics.getExtras().get("statistics"); imageView.setImageBitmap(picturegraph);
[498]
Chapter 22
Running the Simple Photo app
If you're strolling this app at the emulator, then now might be a great time to barely extrade the
emulator's configuration to boom compatibility.
To do that, click on at the AVD Manager icon withinside the menu bar of Android Studio. Click
at the pencil icon to edit the emulator. Click at the Advanced Settings button. Find the Camera
segment. And set each the Front and Back alternatives to Emulated.
Run the app and click on at the TAKE PICTURE button. You will see that the default digital
digicam app to your tool has opened.
You can take a image with all the identical alternatives which you have whilst taking a
picturegraph beneathneath everyday circumstances. When you've got got taken a picturegraph,
however, you're provided the choice to store or discard the picturegraph:
If you pick out to discard it (via way of means of clicking at the move icon), then whilst
onActivityResult is known as, resultCode
== RESULT_OK can be false, and the code withinside the frame of the if assertion will now no
longer be executed.
[499]
Capturing Images
If you pick out to store it (via way of means of clicking at the tick icon), however, then the image
you took can be displayed in ImageView, as expected:
The preceding figures appearance barely abnormal. They display how the emulator offers with
the use of the digital digicam. If you run this on a actual tool, you may be capable of take a
actual image.
Let's upload this form of capability to Where it is snap, however allow's take matters a touch
similarly too.
Where it is snap – coding the seize Fragment Now we are able to upload the seize capability to
the Where it is snap app. We will enforce the capability of taking pictures an picturegraph from
the digital digicam in addition to permit the person to feature a identify and tags for the
picturegraph. We will now no longer, however, upload any capability to store any of this
statistics, as you may first need to find out about databases earlier than we do.
In education to store the statistics, however, we can meet the Android Uri and File training,
which permit us to perceive and find the pics that the person captures.
The finished app, as it's miles on the stop of this bankruptcy, may be located in Chapter 22/
Where Its Snap 2.
[500]
Chapter 22
We will first upload a format that CaptureFragment will use, and we can then upload a few code,
a number of which ought to appearance pretty acquainted via way of means of now, so that you
can seize an picturegraph. The subsequent chapters will then examine databases to store and
display all our statistics.
Creating the format for the seize Fragment You can upload all of the String assets and
identityentification residences manually in case you like, however the quickest manner to
continue is to duplicate the following code into the capture_fragment.xml document. Be certain
to study the code, however, and make a intellectual be aware of the identityentification
residences, as this could make it less complicated a good way to observe alongside whilst we
code the CaptureFragment elegance quickly.
"http://schemas.android.com/apk/res/android"
android:orientation=
"vertical" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textual content="@string/seize"
android:identityentification="@+identityentification/btnCaptur e"
android:layout_marginBottom="28dp"
android:layout_alignParentBottom="genuine"
android:layout_alignParentLeft="genuine"
android:layout_alignParentStart="genuine"
android:layout_marginLeft="25dp"
android:layout_height="150dp"
android:identityentification="@+identityentification/imageView
"
android:src="@mipmap/ic_launcher"
android:layout_below="@+identityentification/editTextTitle"
android:layout_height="wrap_content"
[501]
Capturing Images
android:textual content="@string/store"
android:identityentification="@+identityentification/btnSave"
android:layout_alignTop="@+identityentification/btnCapture"
android:layout_alignParentRight="genuine"
android:layout_alignParentEnd="genuine"
android:layout_marginRight="22dp"
android:layout_marginEnd="22dp" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:identityentification="@+identityentification/editTextTit le"
android:hint="@string/enter_photo_title"
android:layout_alignParentTop="genuine"
android:layout_height="wrap_content"
android:identityentification="@+identityentification/editTextTa g1"
android:hint="@string/tag1"
android:layout_marginBottom="121dp"
android:layout_above="@+identityentification/btnCapture"
android:layout_alignLeft="@+identityentification/btnCapture"
android:layout_alignStart="@+identityentification/btnCapture"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:identityentification="@+identityentification/editTextTa g2"
android:hint="@string/tag2"
android:layout_alignTop="@+identityentification/editTextTag1"
android:layout_alignLeft="@+identityentification/editTextTag1"
android:layout_alignStart="@+identityentification/editTextTag1
"
android:layout_height="wrap_content"
android:identityentification="@+identityentification/editTextTa g3"
android:hint="@string/tag3"
android:layout_above="@+identityentification/btnCapture"
android:layout_alignLeft="@+identityentification/btnCapture"
android:layout_alignStart="@+identityentification/btnCapture"
/>
[502]
Chapter 22
Take a glance and make certain that your format seems as proven withinside the subsequent
figure. However, it does not ought to be exact, the identityentification residences do, and for the
coding we do in Chapter 27, Going Local – Hola! to paintings successfully, we want to apply the
string assets (as withinside the previous code) and now no longer hardcode some thing:
Most of this code can be pretty simple due to the education we've completed, however I will
factor out all of the new code because it arises.
Open it up now and upload the highlighted strains withinside the subsequent code listing:
model="1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
[503]
Capturing Images
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:label="@string/app_name" >
<class android:call="android.intent.class.
LAUNCHER" />
As we can quickly see, we can be growing our personal document, a good way to be used to
store the picturegraph.
permission.
The filepath for the picturegraph String mCurrentPhotoPath; Where the captured picturegraph is
saved personal Uri mImageUri = Uri.EMPTY;
@Override
savedInstanceState)fantastic.onCreate(savedInstanceState);
In the onCreateView technique, that is proven subsequent, we get a connection with every of our
UI widgets, ImageView, each the Button widgets, and the 4 EditText.
We then upload an nameless elegance to concentrate for the person clicking at the Capture
button. In the onClick technique,
in our mini app. The best distinction this time is that the motion is taking area in onCreateView
rather than onCreate, as required whilst managing a Fragment.
[504]
Chapter 22
In addition, we create a brand new document for our picturegraph via way of means of calling
the createImageFile technique that we can write quickly. After this, we use the Uri.fromFile
technique to get a URI, which factors to our newly created document. We will speak extra
approximately what URIs are in Chapter 24, Adding a Database to Where It's Snap whilst we use
them to keep photographs in our database. For now, we are able to think about them as a
hyperlink to the picturegraph.
Note that we then use the putExtra technique to feature this identical Uri to the Intent elegance.
This has the impact of telling the digital digicam app to make this Uri factor to the area wherein
the picturegraph is saved. In impact, we've a hyperlink to the picturegraph as a way to be
captured.
Note that the following code does now no longer cope with the Save button. We will do that
whilst you discover ways to cope with the statistics in more than one chapters.
@Override
Inflate the format document then get all essential references View view =
inflater.inflate(R.format.fragment_capture, container, false);
mImageView =
(EditText)view.findViewById(R.identityentification.editTextTitle)
(EditText)view.findViewById(R.identityentification.editTextTag1)
(EditText)view.findViewById(R.identityentification.editTextTag3)
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
Intent cameraIntent =
new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
[505]
Capturing Images
attempt {
photoFile = createImageFile();
!= null) {
mImageUri = Uri.fromFile(photoFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
});
go back view;
Next, allow's write that new createImageFile technique. The complete info of this technique are
truly convoluted, however they do want to be.
All we're sincerely doing is growing a brand new document. This might have been completed in
a unmarried line of code. The cause our code is a good deal extra verbose than one line is due to
the fact we use SimpleDateFormat and its associated training and strategies to create a
completely unique filename to ensure that our document does not get repeated because the
person takes increasingly more pictures.
Note that the ultimate issue the technique does is go back the File connection with the calling
code:
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
imageFileName, // filename
[506]
Chapter 22
".jpg", // extension
storageDir // folder
);
Now, upload the onActivityResult technique into the CaptureFragment elegance to set the
captured Bitmap picturegraph to ImageView:
@Override
resultCode == Activity.RESULT_OK) {
attempt {
mImageView.setImageURI(Uri.parse(mImageUri.toString()));
}trap(Exception e){
}else{
mImageUri = Uri.EMPTY;
We additionally want to override onDestroy in order that we are able to easy up after ourselves.
This subsequent code receives Bitmap from the drawable, and via way of means of calling its
chained getBitmap(). recycle() strategies, we are able to save you the opportunity of the app
strolling out of reminiscence:
public void onDestroy(){
high-quality.onDestroy();
BitmapDrawable bd = (BitmapDrawable)
mImageView.getDrawable();
bd.getBitmap().recycle();
mImageView.setImageBitmap(null);
Now, we are able to take a look at the picturegraph taking pictures capability.
[507]
Capturing Images
Run the Where it is snap app and faucet on Capture withinside the navigation drawer. You can
now upload tags and a identify and seize an picturegraph:
Of direction, we've the moderate difficulty that none of our customers' statistics is saved.
Summary
In this bankruptcy, we noticed the way to use different apps established on our customers' tool to
get statistics from them.
Specifically, we discovered to get an picturegraph from the digital digicam app, however we
additionally understand that we are able to use comparable strategies with many different apps;
however, that is past the scope of this novices guide.
In the following chapters, you may first study the essential strategies after which we can enforce
a manner to store the customers' statistics the use of an SQLite database. Databases are a totally
green manner to keep statistics in our apps.
Certainly, there might be not anything incorrect with the use of JSON on this app, simply as we
did in Chapter 15, Android Intent and Persistence , however we can see a few blessings of the
use of a database because the venture proceeds. The least of a good way to be the capacity to
effortlessly type our statistics, in addition to upgrade/replace the shape of the statistics.
It is viable to effectively save very huge quantities of information with JSON, however while we
want to apply this information selectively, rather than surely limiting ourselves to the alternatives
of "keep the whole lot" and "load the whole lot", we want to reflect onconsideration on which
different alternatives are to be had.
A desirable pc technology route might in all likelihood train the algorithms vital to address
sorting and filtering our information, however the efforts worried to do that might be pretty
extensive. Also, what are the possibilities folks arising with an answer this is as desirable as one
provided through the those who offer us with the Android API?
As usually, it makes experience for us to apply the answers furnished withinside the Android
API. As we've visible, JSON and SharedPreferences lessons have their location, however at a
few factor, we want to transport directly to the usage of actual databases for actual-international
answers. Android makes use of the SQLite database control gadget, and as you will expect, there
may be an API to make this as smooth as viable.
Find out precisely what a database is Learn what SQL and SQLite are
Learn the fundamentals of the SQL language Take a study the Android SQLite API
[509]
Database 101
Let's solution an entire bunch of database-associated questions after which we are able to get
commenced with making apps that use SQLite. So, what's a database?
What is a database?
A database is each an area of garage and the method to retrieve, save, and manage information. It
enables to visualise a database earlier than getting to know a way to use it. The real shape of the
internals of a database varies substantially relying upon the database in query. SQLite really
shops all its information in a unmarried record.
Think approximately a database with names and examination rankings. Take a study the
subsequent visible illustration of this information to recognize how a database might appearance:
Note, however, that there may be a further column of information right here: an _ID column. We
will communicate extra approximately this as we continue. This unmarried spreadsheet-like
shape is referred to as a desk. As referred to earlier than, there is probably, and regularly are,
more than one tables in a database. Each column of the desk could have a call that may be cited
while we communicate approximately the database.
What is SQL?
SQL stands for Structured Query Language. It is the syntax this is used to get matters finished
with the database.
What is SQLite?
SQLite is the call of the whole database gadget this is preferred through Android, and it has its
very own model of SQL. The cause the SQLite model of SQL desires to be barely one of a kind
than a few different variations is due to the fact the database has one of a kind capabilities.
The SQL syntax primer that follows may be targeted at the SQLite model.
[510]
Chapter 23
The SQL syntax primer
Before you discover ways to use SQLite with Android, you first want to analyze the
fundamentals of a way to use SQLite in fashionable in a platform-impartial context.
Let's study a few instance SQL code that would be used on an SQLite database immediately,
with none Java or Android lessons, after which we are able to extra effortlessly recognize what
our Java code will doing later.
SQL has key phrases similar to Java that purpose matters to show up. Here is a taste of a number
of the SQL key phrases that we can be the usage of quickly:
INSERT: This permits us to feature information to the database DELETE: This permits us to
take away information from the database
WHERE: This permits us to specify the elements of the database that fit a precise standards that
we need to insert, delete, or pick information from
There are many extra SQLite key phrases than this, and for a complete listing of key phrases, test
https://sqlite.org/
lang_keywords.html.
integer: This is simply what we want to save entire numbers textual content: This is best for
storing a easy call or address actual: This is used for huge floating factor numbers There are
many extra SQLite sorts than this, and for a complete listing of sorts, test https://www.sqlite.org/
datatype3.html.
Let's study how we are able to integrate those sorts with the key phrases to create tables and
upload, take away, adjust, and examine information the usage of complete SQLite statements.
[511]
It might be a wonderfully first rate query to invite why we do not create a brand new database
first. The cause for that is that each app has get entry to to an SQLite database through default.
The database is non-public to that app. Here is the declaration that we'd use to create a desk
inside that database.
_ID integer number one key autoincrement now no longer null, call textual content now no
longer null,
rating int;
The preceding code creates a desk referred to as StudentsAndGrades with a row id of the integer
kind a good way to be mechanically increased (incremented) on every occasion a row of
information is introduced.
The desk can even have a call column a good way to be of the textual content kind and can't be
clean (now no longer null).
It can even have a rating column a good way to be of the int kind. Also observe that the
declaration is finished through a semicolon.
Here is how we would insert a brand new row of information into that database:
(call, rating)
VALUES
("Bart", 23);
The preceding code introduced a row to the database. After the previous declaration, the database
could have one access with the 1, "Bart", and 23 values for the _ID, call, and rating columns.
Here is how we would insert some other new row of information into that database:
(call, rating)
VALUES
("Lisa", 100);
The preceding code introduced a brand new row of information with the 2, "Lisa", and 100
values for the _ID, call, and rating columns.
[512]
Chapter 23
Our spreadsheet-like shape might now appearance as proven on this subsequent figure:
Here is how we'd get entry to all of the rows and columns from our database:
The preceding code asks for each row and column. The * image may be examine as all.
The preceding code might handiest go back 100, which, of route, is the rating related to the call
Lisa.
We may even upload new columns after the desk has been created and information has been
introduced. This is straightforward as a long way because the SQL is worried however can
purpose a few problems with reference to
customers' information on already posted apps. We will discover this hassle extra in Chapter 26,
Upgrading SQLite –
Adding Locations and Maps. The subsequent declaration provides a brand new column referred
to as age this is of the int kind:
ADD
age int;
There are many extra information sorts, key phrases, and the approaches to apply them than
we've visible thus far. We will see lots of them withinside the database-pushed apps that we can
construct. This become only a taste. Next, let's study the Android SQLite API, and now we can
start to see how we are able to use our new SQLite abilities.
There are some of one of a kind approaches wherein the Android API makes it pretty smooth for
us to apply our app's database. The first magnificence we want to get acquainted with is
SQLiteOpenHelper.
[513]
The SQLiteDatabase magnificence is the magnificence that represents the real database. The
SQLiteOpenHelper magnificence, however, is wherein maximum of the motion takes location.
This magnificence will allow us to get get entry to to a database and initialize an example of
SQLiteDatabase.
In addition, the SQLiteOpenHelper magnificence, which we can make bigger in our impending
mini app, has strategies to override. First, it has an onCreate technique, that's referred to as the
primary time a database is used, and consequently it makes experience that we location our SQL
on this technique to create our desk shape.
The different technique we ought to override is onUpgrade, which, as you could in all likelihood
guess, is referred to as while we improve our database (ALTER its shape). Exactly how this
works is first-rate defined with a sensible instance, which we can see in some bankruptcy's time.
know-how grows, our SQL statements gets pretty lengthy and awkward. The capacity for
mistakes is excessive.
The manner wherein we can assist conquer the hassle of complexity is through constructing our
queries from elements right into a String. We can then skip this String to the technique (we can
see this quickly) a good way to execute the question for us.
Furthermore, we can use very last strings to symbolize matters inclusive of desk and column
names in order that we cannot get in a clutter with them.
For instance, we ought to claim the subsequent individuals that could constitute the desk names
and column names from the sooner fictitious instance. Note that we can additionally supply the
database itself a call and feature a string for that too: non-public static very last String
DB_NAME = "MyCollegeDB"; non-public static very last String TABLE_S_AND_G = "
StudentsAndGrades";
public static very last String TABLE_ROW_ID = "_id"; public static very last String
TABLE_ROW_NAME = "call"; public static very last String TABLE_ROW_SCORE =
"rating"; As you could see withinside the previous code, we can advantage from getting access to
the string out of doors the magnificence as properly due to the fact we claim it public.
[514]
Chapter 23
We ought to then construct a question like this subsequent instance. The following instance
provides
a brand new access to our hypothetical database and contains our Java variables into the
SQL declaration:
"VALUES (" +
rating +
");";
Note that withinside the preceding code, the normal Java variables call and rating are
highlighted. The preceding String referred to as question is now the SQL declaration this is
precisely equal to the subsequent code:
call, rating)
VALUES ('Divij',94);
It isn't always important to absolutely draw close the preceding blocks of code on the way to
continue with getting to know Android programming. But in case you need to construct your
very own apps and assemble SQL statements that do precisely what you want, it will assist to
accomplish that. Why now no longer examine the preceding blocks of code on the way to parent
the distinction among the pairs of double quote marks "
which are the elements of the String joined collectively with +, the pairs of unmarried quote
marks ' which are a part of the SQL
syntax, the normal Java variables, and the awesome semicolons from the SQL declaration
withinside the String and Java.
Throughout the typing of the question, Android Studio activates us the names of our variables,
making the possibilities of an mistakess an awful lot much less probably although it is extra
verbose than surely typing the question.
Now, we are able to use the lessons that we brought formerly to execute the question:
This is the real database non-public SQLiteDatabase db; Create an example of our inner
CustomSQLiteOpenHelper magnificence
[515]
CustomSQLiteOpenHelper helper =
new CustomSQLiteOpenHelper(context);
db = helper.getWritableDatabase();
When including information to the database, we can use execSQL, as withinside the preceding
code, and while getting information from the database, we can use the rawQuery technique, as
proven withinside the subsequent code snippet: Cursor c = db.rawQuery(question, null);
Note that the rawQuery technique returns an item of the Cursor kind.
There are numerous one of a kind approaches wherein we are able to engage with SQLite, and
that they every have their benefits and disadvantages. Here, we've selected to apply uncooked
SQL statements, as it's far absolutely obvious as to what we're doing and on the equal time, we
can be reinforcing
our know-how of the SQL language. Refer to the subsequent tip in case you need to recognise
extra.
Database cursors
In addition to the lessons that supply us get entry to to the database and the strategies that permit
us to execute our queries, there may be the problem of precisely how the outcomes that we get
lower back from our queries are formatted.
Fortunately, there may be the Cursor magnificence. All our database queries will go back
gadgets of the Cursor kind. We can use the strategies of the Cursor magnificence to selectively
get entry to the information back from the queries like we have got used on this code:
Log.i(c.getString(1), c.getString(2));
The preceding code might output to logcat the 2 values saved withinside the first columns of the
end result that the question back. It is the Cursor item itself that determines which row of our
back information we can presently examine.
We can get entry to some of strategies of the Cursor item together with the moveToNext
technique, which unsurprisingly might flow Cursor to the subsequent row that is prepared for
analyzing:
c.moveToNext();
[516]
Chapter 23
/*
This equal code now outputs the information withinside the first and 2d column of the back
*/
Log.i(c.getString(1), c.getString(2));
On a few occasions, we can be capable of bind Cursor to part of our UI (inclusive of ListView)
and simply go away the whole lot to the Android API. We will see this while we upload a
database to the Where it is snap app withinside the subsequent bankruptcy.
There are many extra beneficial strategies of the Cursor magnificence, a number of which we can
see quickly.
This advent to the Android SQLite API definitely handiest scratches the floor of its capabilities.
We will stumble upon some extra strategies and lessons as we continue in addition. It is,
however, really well worth analyzing in addition in case your app concept calls for complicated
information control. If you need to recognise extra, I advise you examine Android Database
Programming, Jason Wei, Packt Publishing, which you could discover at https://www.
packtpub.com/application-development/android-database-programming.
Now, we are able to see how all this principle comes collectively and the way we can shape our
database code in an real running mini app.
In this segment, we can positioned into exercise the whole lot which you have found out thus far
and create a mini database that allows us to feature, delete, search, and pick information.
First, let's create a brand new mission with all of the settings at their default values and phone it
Database. The code for this mini app is withinside the down load package of the Chapter 23/
Database folder.
Create the format through copying and pasting the subsequent block of XML code. There is not
anything new or complex withinside the code, however make certain to study it to make a
intellectual observe of the numerous id residences at the EditText and Button widgets as it will
make know-how the Java code easier.
[517]
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft=
"@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editName"
android:hint="Type a call"
android:layout_alignParentTop="genuine"
android:layout_height="wrap_content"
android:id="@+id/editAge"
android:layout_below="@+id/editName"
android:layout_alignLeft="@+id/editName"
android:layout_height="wrap_content"
android:textual content="INSERT"
android:id="@+id/btnInsert"
android:layout_below="@+id/editAge"
android:layout_toRightOf="@+id/editSearch"
android:layout_toEndOf="@+id/editSearch"
android:layout_height="wrap_content"
android:textual content="DELETE"
android:id="@+id/btnDelete"
[518]
Chapter 23
android:layout_above="@+id/btnSearch"
android:layout_alignParentRight="genuine"
android:layout_alignParentEnd="genuine"
android:layout_height="wrap_content"
android:id="@+id/btnSelect"
android:layout_alignParentBottom="genuine"
android:layout_alignRight="@+id/editName"
android:layout_height="wrap_content"
android:textual content="Search"
android:id="@+id/btnSearch"
android:layout_above="@+id/btnSelect"
android:layout_alignLeft="@+id/btnDelete"
android:layout_alignStart="@+id/btnDelete"
android:layout_height="wrap_content"
android:id="@+id/editSearch"
android:hint="call to search"
android:layout_alignBottom="@+id/btnSearch"
android:layout_alignParentLeft="genuine"
android:id="@+id/editDelete"
android:hint="call to delete"
android:layout_alignBottom="@+id/btnDelete"
android:layout_alignParentLeft="genuine"
android:layout_alignParentStart="genuine"
android:focusableInTouchMode="genuine" />
[519]
Here is the finished format withinside the Android Studio fashion dressmaker:
We will create a category that manages our database through imposing SQLiteOpenHHelper. It
can even outline some very last Strings to symbolize the names of the desk and its columns.
Furthermore, it's going to deliver a group of helper strategies that we are able to name to carry
out all of the vital queries.
Where vital, those helper strategies will go back a Cursor item that we are able to use lower back
in MainActivity to show the information that we've retrieved. It might be trivial then to feature
new helper strategies must our app want to evolve.
Create a brand new magnificence referred to as DataManager and upload the subsequent member
variables:
[520]
Chapter 23
/*
Next we've a public static very last string for every row/desk that we want to consult each
outside and inside this magnificence
*/
public static very last String TABLE_ROW_ID = "_id"; public static very last String
TABLE_ROW_NAME = "call"; public static very last String TABLE_ROW_AGE = "age";
/*
Next we've a non-public static very last strings for every row/desk that we want to consult simply
internal this magnificence
*/
"names_and_addresses";
Next, we upload the constructor a good way to create an example of our custom model of
SQLiteOpenHelper. We will really put in force this magnificence as an internal magnificence
quickly. The constructor additionally initializes the db member, that's our SQLiteDatabase
reference.
Add the subsequent constructor that we simply mentioned to the DataManager magnificence:
CustomSQLiteOpenHelper helper =
new CustomSQLiteOpenHelper(context);
db = helper.getWritableDatabase();
}
Now, we are able to upload the helper strategies that we can get entry to from MainActivity.
First, the insert technique that executes an INSERT SQL question primarily based totally at the
call and age parameters which are surpassed into the technique.
[521]
// Insert a file
"VALUES (" +
");
";
db.execSQL(question);
This subsequent technique referred to as delete will delete a file from the database if it has an
identical fee withinside the call column to that of the only surpassed withinside the call
parameter. It achieves this the usage of the SQL DELETE keyword.
// Delete a file
public void delete(String call){
Delete the info from the desk if already exists String question =
db.execSQL(question);
Next, we've the selectAll technique that still does as its call suggests. It achieves this with a
SELECT question the usage of the * parameter, that's equal to specifying all of the columns
individually. Also observe that the technique returns Cursor, which we can use withinside the
MainActivity magnificence.
[522]
Chapter 23
Add the selectAll technique to the DataManager magnificence: Get all of the facts public Cursor
selectAll() {
TABLE_N_AND_A, null);
go back c;
Now, we upload a searchName technique, which has a String parameter for the call the consumer
desires to look for. It additionally returns Cursor, with the intention to comprise all of the entries
that had been observed. Note that the SQL
TABLE_ROW_NAME +
go back c;
Finally, for the DataManager magnificence, we create an internal magnificence a good way to be
our implementation of SQLiteOpenHelper. It is a barebones implementation, and over the route
of some chapters, we can make a extra superior implementation that still handles the mission of
upgrading the database for our Where it is snap app.
We have a constructor that gets a Context item, the database call, and the database model. We
will see how the database model is beneficial in Chapter 26, Upgrading SQLite – Adding
Locations and Maps.
We additionally override the onCreate technique, which has the SQL declaration that creates our
database desk with the _ID, call, and age columns.
The onUpgrade technique is left deliberately clean for this mini app.
[523]
This technique handiest runs the primary time the database is created @Override
Create a desk for pics and all their info String newTableQueryString = "create desk "
TABLE_ROW_ID
TABLE_ROW_NAME
TABLE_ROW_AGE
Now, we are able to upload code to apply our new DataManager magnificence.
Coding MainActivity
Make MainActivity put in force View.OnClickListener in order that it may pay attention for
button clicks. Also, upload the subsequent individuals for every of the EditText and Button
widgets. Note additionally that we claim an item of the DataManager kind.
[524]
Chapter 23
Amend the MainActivity magnificence as we simply mentioned in order that it suits the
subsequent code: public magnificence MainActivity extends AppCompatActivity implements
View.OnClickListener{
For all our buttons and edit textual content Button btnInsert; Button btnDelete; Button btnSelect;
Button btnSearch; EditText editName;
EditText editAge;
EditText editDelete;
EditText editSearch;
@Override
setContentView(R.format.activity_main);
Now, we upload code to onCreate that initializes DataManager (dm) through calling its
constructor, receives a connection with
all of the EditText and Button widgets withinside the format, and units a listener for every of the
buttons.
@Override
setContentView(R.format.activity_main);
dm = new DataManager(this);
[525]
btnSelect.setOnClickListener(this);
btnInsert.setOnClickListener(this);
btnDelete.setOnClickListener(this);
btnSearch.setOnClickListener(this);
Now, upload a way a good way to print out the contents of our Cursor back through a number of
our DataManager strategies.
The moveToNext technique returns genuine or false relying upon whether or not there may be
some other row of information in Cursor. So, wrapping it because the circumstance for a whilst
declaration will ensure that each one the back entries are examine and output to the logcat.
Add the showData technique to MainActivity: Output the cursor contents to the log public void
showData(Cursor c){
whilst (c.moveToNext()){
Log.i(c.getString(1), c.getString(2));
Now, we are able to put in force the overridden onClick technique to address all of the buttons.
Note how the R.id.btnSearch case of the transfer declaration calls the correct technique of the
DataManager magnificence with the correct EditText contents through chaining the getText and
toString strategies immediately in the showData technique name. The impact of that is to skip the
back Cursor item to the showData technique with handiest one line of code.
The R.id.btnInsert and R.id.btnDelete instances surely skip the contents of the correct EditText
widgets to the insert and delete strategies of the DataManager magnificence respectively.
@Override
transfer (v.getId()){
case R.id.btnInsert:
dm.insert(editName.getText().toString(),
[526]
Chapter 23
editAge.getText().toString());
break;
case R.id.btnSelect:
showData(dm.selectAll());
break;
case R.id.btnSearch:
showData(dm.searchName(editSearch.getText().toString()));
break;
case R.id.btnDelete:
dm.delete(editDelete.getText().toString()); break;
Add some names and a long time to the database through typing a call and an age observed
through tapping INSERT, as proven withinside the following screenshot:
[527]
After you've got got introduced some names, strive tapping the SELECT button after which take
a look at the output withinside the logcat window:
Note that simply the rows matching the quest time period are back:
Finally, kind a call in EditText subsequent to the DELETE button after which faucet at the
DELETE button:
Now, click on on SELECT and we are able to see that "bob" is now no longer a part of the
database:
Summary
We blanketed lots on this bankruptcy. You found out approximately databases and, in particular,
the database of
Android apps, SQLite. We practiced the fundamentals of speaking with a database the usage of
the SQL language.
We noticed how the Android API enables us use a SQLite database, and we carried out our first
running app with a database.
In the subsequent bankruptcy, we can use a extra superior DataManager magnificence, and we
can additionally use it in the Where it is snap app to keep all our consumer's titles, tags, and pics.
[528]
In this bankruptcy, we can be absolutely targeted on the usage of all we recognise approximately
fragments, interfaces, and SQLite on the way to upload full-size capability to Where it is Snap.
Enabling the saving of pics into the database from the FragmentCapture magnificence
Coding TitlesFragment to reveal a listing of titles both primarily based totally upon a particular
tag or the whole lot of wis_tables_photos
Coding the MainActivity magnificence to address the communications of the fragments through
the interface As traditional, the documents for all the above are withinside the down load
package withinside the Chapter 24/Where Its Snap 3 folder.
[529]
We will want the magnificence to have 4 string individuals for the identify and 3 tags. This is
pretty sincere. The picturegraph
itself, however, is really well worth in addition discussion. We have visible in Chapter 22,
Capturing Images, that we really seize a bitmap from the digital digicam. It is viable to save pix
immediately in a database, however we are able to in all likelihood be extra green than this
whilst on the equal time retaining our code lots easier.
When the digital digicam app in an Android tool takes a picturegraph, it saves it in inner garage
already. If there has been a manner to consult this picturegraph in garage, then we ought to
simply save the region in our database after which load up the picturegraph from the normal
inner garage while we want it.
Such a region is referred to as a URI. In a really simplified manner, we are able to think about a
URI as a record route or address (like an internet address) that factors to a web page,
picturegraph, or different useful resource kind. There is even a Uri magnificence withinside the
Android API to make matters less difficult for us.
So, what precisely is a URI? URI stands for Uniform Resource Identifier, and it's far used to
become aware of a useful resource in a pc gadget or community. If you need to recognise the
overall info of the way URIs paintings (and you've a honest little bit of spare time), then test this
Wikipedia article: https://en.wikipedia.
org/wiki/Uniform_Resource_Identifier.
In addition to our member variables, we can additionally want to feature getter and setter
strategies so we are able to preserve the individuals non-public and nevertheless provide get
entry to to them.
Create a brand new magnificence, name it Photo, and upload the subsequent individuals and
getter and setter strategies that we've mentioned:
import android.net.Uri;
this.mTitle = identify;
go back mStorageLocation;
this.mStorageLocation = storageLocation;
go back mTag1;
this.mTag1 = tag1;
go back mTag2;
this.mTag2 = tag2;
}
public String getTag3() {
go back mTag3;
this.mTag3 = tag3;
[531]
We want an SQLiteDatabase item and an entire bunch of very last string individuals for the desk
and column names.
All the code that we can upload first to our DataManager is sincere, however it's far really well
worth declaring that we can
really have tables on this database. One referred to as wis_table_photos could have a column for
every of the member variables of our Photo magnificence.
Another referred to as wis_table_tags could have simply columns, autoincrement _ID and a tag
column.
The wis_table_photos desk could have a row of information for every and each picturegraph the
consumer takes. The tags column will handiest have a row for every new/specific tag that the
consumer enters. So, if the consumer has multiple picturegraph with the "Barbados" or "2016"
tag, it's going to handiest seem as soon as withinside the wis_table_tags desk however will seem
with every and each picturegraph that makes use of it withinside the wis_table_photos desk.
This manner, it is going to be viable to reveal the consumer a listing of all of the specific tags
they have got introduced, and once they faucet on a tag, it's going to gift them with a listing of all
of the pics which have been tagged with this tag.
It might in all likelihood assist make clear the use of all of the strings withinside the code that
observe to have a spreadsheet eye view to assist visualize our tables:
In the preceding picturegraph, you could see that the wis_table_photos desk has all of the
information that the consumer would possibly input represented for every row. If you study the
subsequent picturegraph, (wis_table_tags) however, you could see that every tag is handiest
saved as soon as. How we
manipulate to insert information to acquire this and the way we manipulate to pick information
turns into
clean as we continue.
[532]
Chapter 24
Remember from the preceding bankruptcy that we claim the member public wherein it's far
beneficial to consult them immediately from some other magnificence. They also are static due
to the fact we do now no longer want new times must we grow to be with multiple
DatabaseManager example.
You is probably thinking wherein the MVC sample and our separate information layer that may
handiest be instantiated as soon as corresponds to this DataManager magnificence. It works due
to the fact all our strings are static and are consequently the equal example throughout more than
one times of
will usually go back the equal database, so it isn't always viable that we can ever grow to be with
more than one out-of-sync databases, and the equal database is mechanically on hand from any
interest of our app.
Add the member variables we've simply mentioned that we can use to construct our database
queries:
/*
Next we've a public static very last string for every row/desk that we want to consult each
outside and inside this magnificence
*/
public static very last String TABLE_ROW_TITLE = "image_title"; public static very last String
TABLE_ROW_URI = "image_uri";
[533]
/*
Next we've a non-public static very last strings for every row/desk that we want to consult simply
internal this magnificence
*/
non-public static very last String DB_NAME = "wis_db"; non-public static very last int
DB_VERSION = 1; non-public static very last String TABLE_PHOTOS =
Now, let's upload the constructor for our DataManager. It surely instantiates a
CustomSQLiteHelper that we can code quickly after which makes use of it to initialize db,
simply as we noticed withinside the preceding bankruptcy.
CustomSQLiteOpenHelper helper =
new CustomSQLiteOpenHelper(context);
db = helper.getWritableDatabase();
We will now be brought to our first helper technique referred to as addPhoto. It takes a Photo
item parameter after which provides all of the values as a brand new row the usage of the getter
strategies of the Photo magnificence, amongst an INSERT
This subsequent code is handiest the primary a part of the addPhoto technique. We will study the
second one element subsequent.
Add the addPhoto technique to the DataManager magnificence: Here are all our helper strategies
public void addPhoto(Photo picturegraph){
[534]
Chapter 24
// Add all of the info to the pics desk
TABLE_ROW_TAG3 +
")"+
"VALUES (" +
");";
Log.i("addPhoto()", question);
db.execSQL(question);
Next, nevertheless in addPhoto, we execute 3 queries, one for every tag, and INSERT them into
the wis_table_tags desk, however note the highlighted WHERE NOT EXISTS clause withinside
the SQL that we construct. This guarantees that we handiest upload a tag if it has now no longer
been introduced already.
TABLE_TAGS +
picturegraph.getTag1() + "');";
db.execSQL(question);
TABLE_TAGS +
[535]
TABLE_TAGS +
picturegraph.getTag3() + "');";
db.execSQL(question);
Now, we've a definitely easy question to get all of the titles from the wis_table_photos desk.
Note that we go back Cursor, which incorporates the information from the question.
Add the getTitles technique to the DataManager magnificence: public Cursor getTitles() {
go back c;
Now we start to see how we can selectively clear out out the titles we show to the consumer. The
getTitlesWithTag technique returns Cursor with picturegraph titles however handiest in the event
that they comprise a particular tag that become surpassed in to the technique.
null);
c.moveToFirst(); go back c;
[536]
Chapter 24
This technique returns all of the columns of a picturegraph with a particular _id fee.
Add the getPhoto technique to the DataManager magnificence: public Cursor getPhoto(int id) {
TABLE_PHOTOS +
c.moveToFirst();
go back c;
The subsequent technique returns all of the tags, that's simply what we can want for our
TagsFragment magnificence.
Add the getTags technique to the DataManager magnificence: public Cursor getTags(){
go back c;
As withinside the final bankruptcy, we've the equal easy constructor, however the onCreate
technique builds and executes queries to create each of our required tables.
The onUpgrade technique may be left clean till Chapter 26, Upgrading SQLite – Adding
Locations and Maps.
This technique handiest runs the primary time the database is created @Override
[537]
Create a desk for pics and all their info String newTableQueryString = "create desk "
TABLE_ROW_ID
TABLE_ROW_TITLE
TABLE_ROW_URI
TABLE_ROW_TAG1
TABLE_ROW_TAG2
TABLE_ROW_TAG3
TABLE_ROW_ID
TABLE_ROW_TAG
" textual content now no longer null" + ");"; db.execSQL(newTableQueryString);
@Override
Now that we've carried out our DataManager magnificence and all its helper strategies, we are
able to positioned them to apply and beautify the capabilities of Where it is Snap.
[538]
Chapter 24
Saving a brand new picturegraph from the seize fragment Open up the CaptureFragment.java
record withinside the editor.
We want to feature a brand new member variable for the CaptureFragment magnificence to
maintain our new DataManager magnificence example.
Add the brand new highlighted member variable to CaptureFragment, which we've simply
mentioned:
String mCurrentPhotoPath;
@Override
Now, we are able to initialize the DataManager example through including this highlighted line
of code to the onCreate technique in CaptureFragment:
@Override
mDataManager =
new DataManager(getActivity()
.getApplicationContext());
[539]
Adding a Database to Where It's Snap
Since our DataManager is coded and prepared to be used and we've an initialized example of it,
we are able to cross in advance and put in force the SAVE button. We have already got a
connection with all the applicable EditText widgets in addition to the Button widget through
btnSave.
We can end the activity of saving our information in onCreateView through imposing an
nameless magnificence to address the button click on. Inside the onClick technique, we step via
the subsequent tasks:
First, take a look at that mImageUri has been initialized with if(mImageUri != null).
Next, take a look at that the mImageUri member isn't always empty with if (!mImageUri.
equals(Uri.EMPTY)).
Assuming we've a picturegraph to keep, we input the if block and claim a brand new Photo item.
Store the consumer's identify through calling setTitle and passing withinside the contents of the
mEditTextTitle EditText widget.
Capture the consumer's values for every of the tags in 3 strings, after which use the correct
setters of the Photo magnificence to save them withinside the Photo item.
The final factor we do withinside the if block is to apply our DataManager example to name
addPhoto, and of route, we skip in our simply-constructed Photo item. The DataManager
magnificence will upload all of the information into the specified tables.
At the stop of the if block, we've an else block that grants a pop-up message to the consumer if
she or he attempts to keep a picturegraph that does not exist or if it's far successful.
Add the highlighted code in onCreateView, which we've simply mentioned, proper after the code
that handles the CAPTURE
button:
btnCapture.setOnClickListener(new View.OnClickListener() {
...
...
btnSave.setOnClickListener(new View.OnClickListener() {
@Override
if(mImageUri != null){
if(!mImageUri.equals(Uri.EMPTY)) {
[540]
Chapter 24
Photo picturegraph = new Photo(); picturegraph.setTitle(mEditTextTitle.getText().toString());
picturegraph.setStorageLocation(mImageUri);
display();
}else {
// No picturegraph
LENGTH_LONG).display();
}else {
});
go back view;
We ought to run the app at this factor and in fact start to keep pics to our database. The hassle, of
route, is that we do not but have any manner to look the listing of to be had tags, picturegraph
titles, or any of the pics themselves.
Before TitlesFragment can reply to clicks and display a picturegraph, we want a fraction to
reveal the ones pics. So, let's code a fraction to view pics.
[541]
Displaying a picturegraph from the database Let's begin through constructing a easy format that
our quickly-to-be-constructed fragment can use.
Create a brand new format through proper-clicking at the format folder and choosing New |
Resource format record, naming it fragment_view, and left-clicking OK.
This picturegraph is what we're aiming for, however there may be additionally an unseen
ImageView overlaying the whole format:
To acquire this format, upload the subsequent XML code to the fragment_view.xml record. I
actually have highlighted some factors really well worth noting that we can discuss: model="1.0"
encoding="utf-eight"?>
"http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
[542]
Chapter 24
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/imageView"
android:layout_gravity="center_horizontal" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textual content="@string/show_map"
android:id="@+id/buttonShowLocation"
android:layout_alignParentBottom="genuine"
android:layout_centerHorizontal="genuine"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textView"
android:layout_alignParentTop="genuine"
android:layout_centerHorizontal="genuine"
Notice there may be a button (buttonShowLocation) that makes use of a string useful resource to
set its textual content. This button is prepared for Chapter 26, Upgrading SQLite – Adding
Locations and Maps, after we've found out to address GPS
Also note the id residences of the 3 widgets on the way to higher observe what takes place while
we code our new Fragment magnificence.
Coding the ViewFragment magnificence
Now, we want to feature a few individuals and feature our new magnificence make bigger the
Fragment magnificence. We have a Cursor member prepared to apply the information that we
can snatch from the database. We additionally have an ImageView member, which,
unsurprisingly, may be used to get a connection with the ImageView widget in our format.
[543]
Amend the ViewFragment magnificence to fit the subsequent code as we've simply mentioned:
Now, we hold through including the overridden onCreate technique. First, we claim and initialize
a brand new int variable referred to as role from the Bundle surpassed into onCreate.
From the getInt technique, we are able to see that we are becoming a few information that
become loaded as a key-fee pair with a key of Position. Of route, we have not written any
code to really ship this information but, however we can later withinside the bankruptcy.
Next, we claim and instantiate a DataManager item so we are able to communicate to the
database, after which we initialize our Cursor member through calling the DataManager
technique getPhoto and passing withinside the role variable, whose fee we extracted from Bundle
a second ago.
So now that we've Cursor with Photo in it, we are able to see a way to show it, after which we
are able to see how we skip withinside the role.
Code the onCreate technique withinside the ViewFragment magnificence as we've simply
mentioned:
@Override
getArguments().getInt("Position");
Load the correct picturegraph from db
(getActivity().getApplicationContext());
mCursor = d.getPhoto(role);
As traditional, while we need to initialize the view of a normal Fragment, we accomplish that
withinside the onCreateView technique. Here is how the subsequent block of code works.
We inflate the view as we've finished numerous instances earlier than. Then, we get a connection
with our TextView, Button, and ImageView widgets. We will now no longer, however, be doing
some thing with Button simply but.
[544]
Chapter 24
Then, we see how we get entry to the information in Cursor to set TextView with the identify of
the picturegraph and ImageView with the picturegraph.
Notice that we are able to become aware of the perfect column withinside the back information
(in Cursor) through the usage of the public static strings from our DataManager magnificence.
The DataManager.TABLE_ ROW_TITLE string is the column call for the picturegraph's
identify, and the DataManager.
TABLE_ROW_URI string is, of route, the column call that holds the URI.
We also can see that Cursor has a few beneficial strategies that permit us to apply the names of
the columns to extract the information. They are getString and getColumnIndex.
Add the onCreateView technique we've simply been speakme approximately into the
view.findViewById(R.id.textView);
textView.setText(mCursor.getString
(mCursor.getColumnIndex(DataManager.TABLE_ROW_TITLE)));
mImageView = (ImageView)
view.findViewById(R.id.imageView);
Finally, for the ViewFragment magnificence, we want to override the onDestroy technique. We
accomplish that to ensure that because the consumer perspectives more than one pix (which
might be pretty huge with tremendous cameras on gadgets those days), we name recycle at the
picturegraph we loaded with Uri and set the supply of ImageView to null. This has the impact of
releasing up RAM reminiscence and stops the tool from sooner or later strolling out and
crashing.
[545]
Actually, the tool in all likelihood might not run out of reminiscence, however the quantity of
reminiscence the OS is ready to allocate for our app in all likelihood will.
Add the onDestroy technique we've simply mentioned to the ViewFragment magnificence:
extraordinary.onDestroy();
mImageView.getDrawable();
bd.getBitmap().recycle();
mImageView.setImageBitmap(null);
Now, the app has someplace to reveal the picturegraph related to any titles which are clicked on
through the consumer. It can even want a manner of speaking with our new ViewFragment
earlier than it may accomplish that. So, let's create an interface to do simply that.
to apply for the standards to look for database entries with the matching tag.
This equal interface will deal with all this paintings. MainActivity can then put in force the
interface and deal with the inter-fragment conversation.
Create a brand new magnificence referred to as ActivityComs and code it into our interface
through modifying it to precisely the code proven subsequent:
We now have strategies we are able to use for speaking among our Fragment
lessons and MainActivity. One (onTitlesListItemSelected) will skip in an int to symbolize the _id
of the row in our database of the specified Photo item. The different (onTagsListItemSelected)
will skip a string this is the tag to be looked for and coupled in opposition to rows withinside the
wis_table_photos desk.
[546]
Chapter 24
We will deal with this in 3 degrees:
Finally, we can tie everything collectively and put in force the interface in
MainActivity.
As we can be dipping inside and outside of present strategies in addition to writing new ones, in
case you get disoriented in any manner, surely open up the applicable documents withinside the
Chapter 24/Where Its Snap 3 folder wherein you could see all of the code we upload on this
bankruptcy whole in the correct places.
Coding TitlesFragment
We are definitely near being capable of really display a picturegraph in our Photos app. We want
to load a listing of picturegraph titles from our database into ListView, furnished through
ListFragment, and deal with what takes place while the consumer clicks on a listing object.
Some of the code in right here might not make whole experience till we end coding
MainActivity, with the intention to, of route, deal with the conversation among
Let's upload new individuals to TitlesFragment—a Cursor member to load a few information
into and an example of our new interface.
Add the 2 highlighted member variables wherein proven: public magnificence TitlesFragment
extends ListFragment {
@Override
Get a string to symbolize the tag from Bundle, the usage of getArguments. getString to look for
withinside the database.
[547]
If TitlesFragment gets a tag to look for, it's going to handiest display the picturegraph titles with
that matching tag, however
if it gets no tag, it's going to display all of the titles. With this in thoughts, the if block both
masses the Cursor item up with information the usage of getTitles or getTitlesWithTag.
Then, we name setListAdapter to set our new SimpleCursorAdapter because the adapter for
ListView.
android.com/reference/android/widget/
SimpleCursorAdapter.html.
Add the subsequent highlighted code to onCreate that we've simply mentioned:
@Override
(getActivity().getApplicationContext());
if(tag == "_NO_TAG"){
d.getTitlesWithTag(tag);
[548]
Chapter 24
Create a brand new adapter
SimpleCursorAdapter cursorAdapter =
new SimpleCursorAdapter(getActivity(),
setListAdapter(cursorAdapter);
Now, we are able to deal with what takes place while the consumer faucets on a identify in
ListView. We put in force the onListItemClick technique, and all we want is the role parameter
of this technique on the way to do our paintings.
We use the moveToPosition technique on our Cursor and skip in role to set the cursor to the
proper location for the subsequent line of code.
with the fee of the _id column from the database with this line of code:
mCursor.getColumnIndex(
DataManager.TABLE_ROW_ID));
Finally, we are able to name the onTitlesListItemSelected technique of our interface to skip the
correct _id fee to MainActivity.
Move the cursor to the clicked object withinside the listing mCursor.moveToPosition(role);
mCursor.getColumnIndex(
DataManager.TABLE_ROW_ID));
mActivityComs.onTitlesListItemSelected(dBID);
[549]
Of route, we have not initialized our mActivityComs member but, and we accomplish that the
equal manner we did in Chapter 19, Using Multiple Fragments, and set it to null the equal
manner additionally.
Add the very last strategies to acquire this at the correct instances:
@Override
extraordinary.onAttach(interest);
mActivityComs = (ActivityComs)interest;
@Override
extraordinary.onDetach();
mActivityComs = null;
Coding TagsFragment
All the TagsFragment magnificence desires to do is show a listing of tags from the correct desk
and while the consumer
Add the ActivityComs interface as a brand new member variable as highlighted withinside the
following code: public magnificence TagsFragment extends ListFragment {
non-public ActivityComs mActivityComs;
@Override
@Override
[550]
Chapter 24
As we've visible upon simply coding TitlesFragment, the subsequent code permits us to:
Set up SimpleCursorAdapter and bind it to ListView Add the highlighted code we've simply
mentioned to the onCreate technique:
@Override
(getActivity().getApplicationContext());
Cursor c = d.getTags();
new SimpleCursorAdapter(getActivity(),
setListAdapter(cursorAdapter);
Now, to address the touches. This code does the subsequent: Retrieves a Cursor item from
SimpleCursorAdapter through chaining getAdapter and getCursor after which casting the end
result as a
SimpleCursorAdapter
Creates a string primarily based totally at the tag that become simply clicked
Passes the string to MainActivity the usage of the onTagsListItemSelected technique of the
interface Add the onListItemClick technique that we've mentioned:
[551]
clickedTag);
mActivityComs.onTagsListItemSelected(clickedTag);
Now, we want to address the advent and destruction of our ActivityComs example with the same
old strategies, as proven subsequent:
@Override
extraordinary.onAttach(interest);
mActivityComs = (ActivityComs)interest;
@Override
extraordinary.onDetach();
mActivityComs = null;
Coding the fragment communications in MainActivity We simply want to put in force the
ActivityComs interface and upload an example of our DataManager magnificence. Then, we're
going to deal with the 2 strategies of the interface, and we're desirable to cross.
[552]
Chapter 24
Initialize the DataManager example through including the highlighted line of code in onCreate:
@Override
setContentView(R.format.activity_main);
(DrawerLayout)findViewById(R.id.drawerLayout); mActivityTitle
= getTitle().toString(); …
Now, we can code the onTagsListItemSelected technique. Here, we positioned the surpassed in
string that represents a tag into Bundle and skip it in to the brand new example of
TitlesFragment. We have visible already how TitlesFragment offers with this string.
We have simply obtained a String for the TitlesFragment Prepare a brand new Bundle
fragment.setArguments(args);
mNavDrawerList.setSelection(1);
mDrawerLayout.closeDrawer(mNavDrawerList);
In the onTitlesListItemSelected technique, we've obtained int, which represents the _id of a row
withinside the wis_table_photos desk that desires to be proven to the consumer withinside the
ViewFragment.
The code provides int to Bundle after which provides Bundle to Fragment earlier than beginning
Fragment.
Open ViewFragment with the picturegraph indicated through role public void
onTitlesListItemSelected(int role) {
Load up the package with the row _id Bundle args = new Bundle(); args.putInt("Position", role);
Create the fragment and upload the package ViewFragment fragment = new ViewFragment();
fragment.setArguments(args);
if (fragment != null) {
//setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mNavDrawerList);
} else {
}
}
That become a code-heavy bankruptcy, however now we've the pride of seeing our app in
motion.
[554]
Chapter 24
Running the app thus far
Add a choice of pics, tags, and titles to the database, and run your app. You will see the
subsequent:
On the Tags display, click on on a tag to look a listing of picturegraph titles that comprise that
tag: Adding a Database to Where It's Snap
That might be the maximum code-extensive bankruptcy thus far. It is viable that each element of
the way this works isn't always absolutely clean. The manner to make matters extra clean is to
construct the mission piece through piece. It can also assist to refer lower back to Chapter 19,
Using Multiple Fragments, for a refresher on interfaces.
If there are some cloudy elements in your know-how, this does not ought to forestall you from
transferring on due to the fact the relaxation of the ee-e book will nevertheless offer plenty extra
Android API goodness that isn't always depending on having mastered this bankruptcy.
Next, we can study a way to combine GPS places and Google Maps into our apps.
In this bankruptcy, we're going worldwide or even in short into area. We will see how the
Android API works with the GNSS
Connect with the Google Maps server to get map information Let's begin with a brief assessment
of GPS.
GPS is one of these technology that in no way fails to amaze you whilst you take a seat down
and reflect onconsideration on the way it works. When you furthermore mght keep in mind that a
telecellsmartphone you could installed your pocket is able to the usage of it too, it's far even
extra thoughts-numbingly extraordinary.
Warning: If you had been born after 1990, you may now no longer
recognize the preceding paragraph and in all likelihood think that GPS is pretty dull.
The gadget works with 27 satellites in area referred to as the GNSS. Out of those, 24 of the
satellites are energetic and 3 are a backup. Each satellite tv for pc orbits the Earth each 12 hours
continuously broadcasting the converting role information.
By appearing calculations on information from at the least 3 of those satellites, our tool can offer
us with a region withinside the international in longitude and range. Oversimplifying a touch (ok,
oversimplifying pretty lots), those are the tiers from the poles and equator. They are
extraordinarily particular
meters.
As we already recognise from Chapter 1, The First App, all of the complexity is hidden from us
through the Android API, and we are able to now construct a extraordinary-easy app to look GPS
in motion.
Where withinside the international – the GPS mini app Create a brand new mission and phone it
Where withinside the international.
To deal with Marshmallow runtime permissions, as mentioned in Chapter 11, Widget Mania
withinside the Android permissions and M arshmallows segment, we want to set the target API
to 22.
To do that, pick Android from the drop-down listing on the pinnacle of the mission explorer.
Now, double-click on at the construct.gradle (module: app) alternative from close to the lowest
of the mission explorer window.
Make positive to extrade the highlighted line of code too in order that targetSdkVersion is ready
to 22, as proven on this code snippet: