Sie sind auf Seite 1von 34

Summer Training Project Report

Submitted By:
Shivam Jha
IT-2K13
(CSJMA13001390-160)

Under the Guidance of


S. A. WAHAB
Incredibles Technology, Kanpur
ACKNOWLEDGEMENT

I would like to express my deep gratitude to Mr. S A Wahab, my


internship coordinator for their constant co-operation. He was
always there with his competent guidance and valuable
suggestion throughout the pursuance of project. And for the
great insight in Concepts of Android and Java.
I would also like to place of appreciation to my fellow colleagues
ANKIT, ARVIND and SAMEER for the great coordination and fun in this
learning journey and suggestions for the project.

**********************************************
COMPANY PROFILE

Incredibles Technology is a group of Freelance Web and Software


developers who also has an interest in Training the newbies in this field.
We have developed many Stand-alone applications as well as CRM
applications.
What we Do
Web Hosting
Web Development
Web Designing
SEO & Social Media Marketing
Computer Tech. Training.
INTRODUCTION
What is android?
Android is a software stack for mobile devices that includes an operating system,
middleware and key applications. Android is a software platform and operating system for
mobile devices based on the Linux operating system and developed by Google and the
Open Handset Alliance. It allows developers to write managed code in a Java-like language
that utilizes Google-developed Java libraries, but does not support programs developed in
native code.
The unveiling of the Android platform on 5 November 2007 was announced with the
founding of the Open Handset Alliance, a consortium of 34 hardware, software and telecom
companies devoted to advancing open standards for mobile devices. When released in 2008,
most of the Android platform will be made available under the Apache free-software and
open-source license.

Android History :
THE BIRTH OF ANDROID
Google Acquires Android Inc.
In July 2005, Google acquired Android Inc., a small startup company based in Palo Alto,
CA. Android's co-founders who went to work at Google included Andy Rubin (co-founder
of Danger), Rich Miner (co-founder of Wildfire Communications, Inc), Nick Sears (once
VP at T-Mobile), and Chris White (one of the first engineers at WebTV). At the time, little
was known about the functions of Android Inc. other than they made software for mobile
phones.
2.1.2 Open Handset Alliance Founded
On 5 November 2007, the Open Handset Alliance, a consortium of several companies
which include Google, HTC, Intel, Motorola, Qualcomm, T-Mobile, Sprint Nextel and
NVIDIA, was unveiled with the goal to develop open standards for mobile devices.
ANDROID VERSIONS
Android 1.0 (Angel Cake) : The first version of the open source software
was released back in 2008.
Android 1.1 (Battenberg) : In Feb 2009, version 1.1
Android 1.5 (Cupcake) : Launched in April 2009
Android 1.6 (Donut) : Released in September 2009. Brought the Quick
Search Box and had Screen Size Diversity.
Android 2.0 / 2.1 (clair) : Released in 26 October 2009 and January
2010. Supported High Density Displays and Live Wallpapers which
responds to touch. Supported Google Maps Navigation, Speech to text and
Home Screen Customization.
Android 2.2 (Froyofrozen yogurt) : Released in the summer of 2010.
Android added the support of Voice-Actions and Portable Mobile-Hotspots
and Increased performance.
Android 2.3 (Gingerbread) : Gingerbread landed by the end of 2010.
Added new Gaming APIs, support for NFC and Battery Management.
Android 3.0 (Honeycomb): For the first time Google released a software
that was totally focused on tablets. This version released in July/august
2011. Added System Bars for on-Screen Navigation Controls and Quick
Settings.
Android 4.0 (Ice Cream Sandwich 4.0): Released in October 2011.
Supported custom Home-Screen, data usage control and Android Beam for
sharing over NFC.
Android 4.1 (jelly bean4.1) : Released in 26th June 2012. Google Now
was added and Actionable notifications were also featured. It also
supported multiple users on One Device by Account Switching feature.
Android 4.4 (KitKat) : Voice: OK Google was featured also were
immersive design and smart dialer.
Android 5.0 (Lollypop) : It supports on many devices from watches to
TV. Introduced Material Design and Notifications on Lock Screen.
Android 6.0 (Marshmallow) : Added flexible permissions and the
consumes less battery by optimizing apps.
FEATURES OF ANDROID OS

Application framework enabling reuse and replacement of components

Dalvik virtual machine optimized for mobile devices. Now it works on


Gradle.

Integrated browser based on the open source WebKit engine

Optimized graphics powered by a custom 2D graphics library; 3D graphics


based on the OpenGL ES 1.0 specification (hardware acceleration optional)

SQLite for structured data storage

Media support for common audio, video, and still image formats (MPEG4,
H.264, MP3, AAC, AMR, JPG, PNG, GIF)

GSM Telephony (hardware dependent)

Bluetooth, EDGE, 3G, and WiFi (hardware dependent)

Camera, GPS, compass, and accelerometer etc.(hardware dependent)

Rich development environment including a device emulator, tools for


debugging, memory and performance profiling, and a whole IDE : Android
Studio.
Android Interfaces and Architecture
APPLICATION FRAMEWORK

The application framework is used most often by application developers. As a hardware


developer, you should be aware of developer APIs as many map directly to the underlying HAL
interfaces and can provide helpful information about implementing drivers.

BINDER IPC

The Binder Inter-Process Communication (IPC) mechanism allows the application framework to
cross process boundaries and call into the Android system services code. This enables high level
framework APIs to interact with Android system services. At the application framework level, this
communication is hidden from the developer and things appear to "just work."

SYSTEM SERVICES

Functionality exposed by application framework APIs communicates with system services to


access the underlying hardware. Services are modular, focused components such as Window
Manager, Search Service, or Notification Manager. Android includes two groups of services:
system (services such as Window Manager and Notification Manager) and media (services
involved in playing and recording media).

HARDWARE ABSTRACTION LAYER (HAL)

The hardware abstraction layer (HAL) defines a standard interface for hardware vendors to
implement and allows Android to be agnostic about lower-level driver implementations. The HAL
allows you to implement functionality without affecting or modifying the higher level system. HAL
implementations are packaged into modules (.so) file and loaded by the Android system at the
appropriate time.

LINUX KERNEL

Developing your device drivers is similar to developing a typical Linux device driver. Android uses a
version of the Linux kernel with a few special additions such as wake locks (a memory
management system that is more aggressive in preserving memory), the Binder IPC driver, and
other features important for a mobile embedded platform. These additions are primarily for
system functionality and do not affect driver development.
Android System Architecture
Why Android is better ?

Applications
- Google Applications
Android includes most of the time many Google applications like Gmail, YouTube or Maps.
These applications are delivered with the machine most of the time, except in certain
cases, such as some phones running android on which the provider has replaced Google
applications by its own applications.
-Widgets
With android, it is possible to use widgets which are small tools that can most often get
information. These widgets are directly visible on the main window.
-Android Market
This is an online software store to buy applications. Developers who created applications
can add them into the store, and these applications can be downloaded by users, they can
be both free and paid.

Multitasking
Android allows multitasking in the sense that multiple applications can run simultaneously.
With Task Manager it is possible view all running tasks and to switch from one to another
easily.

SDK
A development kit has been put at disposal of everybody. Accordingly, any developer can
create their own applications, or change the android platform. This kit contains a set of
libraries, powerful tools for debugging and development, a phone emulator, thorough
documentation, FAQs and tutorials.

Modifiability:
This allows everyone to use, improve or transform the functions of Android for example
transform the interface in function of uses, to transform the platform in a real system
embedded Linux.
Build Target Version of Project : Marshmallow(Version 6.0-API Level 23)
Features
i) Fingerprint Authentication
This release offers new APIs to let you authenticate users by using their fingerprint scans
on supported devices, Use these APIs in conjunction with the Android Keystore system.

ii) Confirm Credential


Your app can authenticate users based on how recently they last unlocked their device.
This feature frees users from having to remember additional app-specific passwords, and
avoids the need for you to implement your own authentication user interface.

iii) App Linking


This release enhances Androids intent system by providing more powerful app linking.
This feature allows you to associate an app with a web domain you own. Based on this
association, the platform can determine the default app to use to handle a particular web
link and skip prompting users to select an app.

iv) Direct Share


This release provides you with APIs to make sharing intuitive and
quick for users. You can now define direct share targets that launch a
specific activity in your app. These direct share targets are exposed to
users via the Share menu. This feature allows users to share content
to targets, such as contacts, within other apps.

v) Adoptable Storage Devices


With this release, users can adopt external storage devices such as SD cards. Adopting an
external storage device encrypts and formats the device to behave like internal storage.
This feature allows users to move both apps and private data of those apps between
storage devices.

vi) Assist APIs


This release offers a new way for users to engage with your apps through an assistant. To
use this feature, the user must enable the assistant to use the current context. Once
enabled, the user can summon the assistant within any app, by long-pressing on
the Home button.
vii) 4K Display Mode
The platform now allows apps to request that the display resolution be upgraded to 4K
rendering on compatible hardware. To query the current physical resolution, use the
new Display.Mode APIs. If the UI is drawn at a lower logical resolution and is up scaled to a
larger physical resolution, be aware that the physical resolution
the getPhysicalWidth() method returns may differ from the logical resolution reported
by getSize(). You can request the system to change the physical resolution in your app as it
runs, by setting the preferredDisplayModeId property of your apps window. This feature
is useful if you want to switch to 4K display resolution. While in 4K display mode, the UI
continues to be rendered at the original resolution (such as 1080p) and is up scaled to 4K,
but SurfaceView objects may show content at the native resolution.

viii) Notifications
This release adds the following API changes for notifications:

New INTERRUPTION_FILTER_ALARMS filter level that corresponds to the


new Alarms only do not disturb mode.

New CATEGORY_REMINDER category value that is used to distinguish user-


scheduled reminders from other events (CATEGORY_EVENT) and alarms
(CATEGORY_ALARM).
New Icon class that you can attach to your notifications via
the setSmallIcon() and setLargeIcon() methods. Similarly, the addAction() method
now accepts an Icon object instead of a drawable resource ID.
The Build Process
The build process involves many tools and processes that convert your project into an
Android Application Package (APK). The build process is very flexible, so it's useful to
understand some of what is happening under the hood.
The build process of a typical Android app module
The build process for a typical Android app module, as shown in above figure, follows
these general steps:
The compilers convert your source code into DEX (Dalvik Executable) files, which
include the bytecode that runs on Android devices, and everything else into
compiled resources.
The APK Packager combines the DEX files and compiled resources into a single APK.
Before your app can be installed and deployed onto an Android device, however,
the APK must be signed.
The APK Packager signs your APK using either the debug or release keystore:
If you are building a debug version of your app, that is, an app you intend only
for testing and profiling, the packager signs your app with the debug keystore.
Android Studio automatically configures new projects with a debug keystore.
If you are building a release version of your app that you intend to release
externally, the packager signs your app with the release keystore. To create a
release keystore, read about Signing your app in Android Studio.
Before generating your final APK, the packager uses the zipalign tool to optimize your
app to use less memory when running on a device.
At the end of the build process, you have either a debug APK or release APK of your
app that you can use to deploy, test, or release to external users.
Build Configuration Files
Creating custom build
configurations requires you to make
changes to one or more build
configuration files,
or build.gradle files. These plain text
files use Domain Specific Language
(DSL) to describe and manipulate
the build logic using Groovy, which
is a dynamic language for the Java
Virtual Machine (JVM). You dont
need to know Groovy to start
configuring your build because the
Android Plugin for Gradle
introduces most of the DSL
elements you need. To learn more
about the Android plugin DSL, read
the DSL reference documentation.

When starting a new project, Android Studio automatically creates some of these files for
you, as shown in above figure, and populates them based onsensible defaults.
TOOLS USED IN PROJECT

1. Android Studio 2.2

Instant Run
Push code and resource changes to your app running on a device or
emulator and see the changes instantly come to life.
Instant Run dramatically speeds up your edit, build, and run cycles.

Intelligent Code Editor


Write better code, work faster, and be more productive with an
intelligent code editor that helps you each step of the way.
Android Studio is built on IntelliJ and is capable of advanced code
completion, refactoring, and code analysis.

Robust and Flexible Build System


Easily configure your project to include code libraries and generate
multiple build variants from a single project.
With Gradle, Android Studio offers high-performance build
automation, robust dependency management, and customizable build
configurations.

Code Templates And GitHub Integration


Start projects with code templates for patterns such as navigation
drawer and view pagers, or import Google code samples from
GitHub. Android Studio's project wizards make it easier than ever to
add code in a new project.

CODE TEMPLATES AND SAMPLE APPS


Android Studio includes project and code templates that make it easy
to add well-established patterns such as a navigation drawer and view
pager.
2. Sublime Text 3
Sublime Text is a sophisticated text editor for code, markup and prose.
You'll love the slick user interface, extraordinary features and amazing performance.

3. GENYMOTION Emulator 2.7.2


GENYMOTION is an Android Emulator which
can be attached to Android Studio and Eclipse
to help in developing apps faster.
It supports GPS, Google Play Services and other
service also.
Works faster than Android Studio Emulator.

4. Java JDK 1.8(x64)


Its impossible to do Android Development
without Java JDK. I was using JDK ver1.8 (x64 bit).

5. OpenWeatherMap API
OpenWeatherMap is a website which provides
API for the weather forecasts of various types.
Summer Training Project: Weather APP
A Weather App which shows the weather forecast for
Present day as well as Next 2 Weeks.
It shows the weather forecasts in a very interactive
manner.

For example :

It shows the icons according to weather.

Clear Sky.

Rain.

Light Clouds.

Storm. etc.
Features of the App

Sleek and Nice Design Flow Forecast for next 2-Weeks

Only Important details on Front Weather In Detail on Click


Change location according to ZIP code Change Unit (C to F)

Notifies on Day Change Share the Weather


Project Documentation
The Code is written in a very clear and concise manner as well as
understandable to everyone.
For example, the variables, functions and Filenames are given
meaningfully.
Folder Structure
app
o src
main
AndroidManifest.xml
java
o com.example.android.sunshine.app
data
WeatherContract.java
WeatherDbHelper.java
WeatherProvider.java
sync
SunshineAuthenticator.java
SunshineAuthenticatorService.java
SunshineSyncAdapter.java
SunshineSyncService.java
DetailActivity.java
DetailFragment.java
ForecastAdapter.java
ForecastFragment.java
MainActivity.java
SettingsActivity.java
Utility.java
res
o drawable(dir)
o drawable-hdpi(dirs) etc.
o layout(dir)
o menu(dir)
o values(dir)
o xml(dir)
androidTests
java
o com.example.android.sunshine.app(dir)
Starting with MainActivity.java.
A Fragment is included in MainActivity which is ForecastFragment.java.
MainActivity.java has few methods and variables. It extends
ActionBarActivity (It is deprecated in further versions) .
Methods:
onCreate() : It is called first when the app is launched and
MainActivity is created. It also checks if the display is wide or large i.e
of a Tablet then it populates the MainActivity with MasterDetail view,
otherwise with a simple Listview containing Fragment.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLocation = Utility.getPreferredLocation(this);
setContentView(R.layout.activity_main);
if (findViewById(R.id.weather_detail_container) != null) {
// For Large Screen Layouts.
mTwoPane = true;
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.weather_detail_container, new DetailFragment(),
DETAILFRAGMENT_TAG)
.commit();
}
} else {
mTwoPane = false;
getSupportActionBar().setElevation(0f);
}

ForecastFragment forecastFragment =
((ForecastFragment)getSupportFragmentManager()
.findFragmentById(R.id.fragment_forecast));
forecastFragment.setUseTodayLayout(!mTwoPane);

SunshineSyncAdapter.initializeSyncAdapter(this);
}

As shown in code it is including a fragment fragment_forecast.xml.


Also its initializing Apps SyncAdapter so that it keeps on getting
data from API in a fixed interval.
onCreateOptionsMenu() : It inflates the menu. This adds items to
the actionbar if it is present.
onOptionsItemSelected() : When any option is tapped this method
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
startActivity(new Intent(this, SettingsActivity.class));
return true;
}

return super.onOptionsItemSelected(item);
}

is called. If it is Settings item then it invokes SettingsActivity.


onItemSelected() : In two-pane mode it shows detail view by adding
or replacing the detailfragment. Otherwise, it starts a new Detail
activity.
onResume() : If the activity was paused then after app is again
visible this method is invoked. It updates the location and date.

DetailActivity.java : It is invoked when an item is tapped in the main


activity view. It shows more detailed weather forecast for that day.
onCreate() : It is creating the Detail fragment and adding to the
activity.

protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
if (savedInstanceState == null) {
Bundle arguments = new Bundle();
arguments.putParcelable(DetailFragment.DETAIL_URI, getIntent().getData());
DetailFragment fragment = new DetailFragment();
fragment.setArguments(arguments);

getSupportFragmentManager().beginTransaction()
.add(R.id.weather_detail_container, fragment).commit(); }
}

onCreateOptionsMenu() : It works same in all activity.


onOptionsItemSelected() : When any option is tapped this method
is called. If it is Settings item then it invokes SettingsActivity.
ForecastFragment.java : This file encapsulates fetching the forecast and
displaying it in ListView.
onCreateView() : Here the forecastAdapter will take data from
source and use it to populate the listview. Here if the device is turned
sideways it is appeared to use the space and takes advantage of the

public View onCreateView(LayoutInflater inflater, ViewGroup container,


Bundle savedInstanceState) {
mForecastAdapter = new ForecastAdapter(getActivity(), null, 0);

View rootView = inflater.inflate(R.layout.fragment_main, container, false);

mListView = (ListView) rootView.findViewById(R.id.listview_forecast);


mListView.setAdapter(mForecastAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Cursor cursor = (Cursor) adapterView.getItemAtPosition(position);
if (cursor != null) {
String locationSetting = Utility.getPreferredLocation(getActivity());
((Callback) getActivity())
.onItemSelected(WeatherContract.WeatherEntry.buildWeatherLocationWithDate(
locationSetting, cursor.getLong(COL_WEATHER_DATE)
));
}
mPosition = position;
}
});

if (savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY)) {


mPosition = savedInstanceState.getInt(SELECTED_KEY);
}

mForecastAdapter.setUseTodayLayout(mUseTodayLayout);

return rootView;
}

room.
onActivityCreated() : It is called when the fragment's activity has
been created and this fragment's view hierarchy instantiated. It is
creating and initializing the Loader.
public void onActivityCreated(Bundle savedInstanceState) {
getLoaderManager().initLoader(FORECAST_LOADER, null, this);
super.onActivityCreated(savedInstanceState);
}

onLocationChange() : Called when the location is changed. All it is


doing is Restaring things.
updateWeather() : It is using SyncAdapters to synchronise the
weather from OpenWeatherMap API.
openPreferredLocationInMap() : Using URI scheme to show the
location on the map if any receiving apps are installed. If not then it
shows an error-message.
private void openPreferredLocationInMap() {
// Using the URI scheme for showing a location found on a map.
if ( null != mForecastAdapter ) {
Cursor c = mForecastAdapter.getCursor();
if ( null != c ) {
c.moveToPosition(0);
String posLat = c.getString(COL_COORD_LAT);
String posLong = c.getString(COL_COORD_LONG);
Uri geoLocation = Uri.parse("geo:" + posLat + "," + posLong);

Intent intent = new Intent(Intent.ACTION_VIEW);


intent.setData(geoLocation);

if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(intent);
} else {
Log.d(LOG_TAG, "Couldn't call " + geoLocation.toString() + ", no receiving apps
installed!");
Toast.makeText(getActivity(),"No Receiving Apps
Installed.",Toast.LENGTH_SHORT).show();
}
}
}
}

onSaveInstanceState() : When tablet rotates, the currently selected


list items needs to be saved.
Loader<Cursor> onCreateLoader() : Called when a new loader is
created. Returns the weather data of current location and date in
sorted order.
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
String sortOrder = WeatherContract.WeatherEntry.COLUMN_DATE +
" ASC";

String locationSetting =
Utility.getPreferredLocation(getActivity());
Uri weatherForLocationUri =
WeatherContract.WeatherEntry.buildWeatherLocationWithStartDate(
locationSetting, System.currentTimeMillis());

return new CursorLoader(getActivity(),


weatherForLocationUri,
FORECAST_COLUMNS,
null,
null,
sortOrder);}
SettingsActivity.java : It is Apps preference Activity that presents set of
application settings.
onCreate() : It is attaching the pref_general.xml to this activity. This
XML file contains the prefernces which are settings for our app. It is
also binding preference summary to the preferences.

public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);

// the UI summary can be updated when the preference changes.

bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
}

bindPreferenceSummaryToValue() : It is attaching the listener to


the preferences. Also invoking the listener once to initialize the
summary.

private void bindPreferenceSummaryToValue(Preference preference) {


preference.setOnPreferenceChangeListener(this);

// Trigger the listener immediately with the preference's


// current value.
onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}

Utility.java : It is a helper file for proper formatting of the data as well as


attaching the proper icon and art according to weather.
formatTemperature() : It formats temperature from metric to
imperial and vice-versa.
getFriendlyDayString() : Converts todays date to display Today,
next day as Tommorrow and then next days of week as Weekdays
and the next Week as a formatted string.
getIconResourceForWeatherCondition() : sets icons based on
weather code data sent by OWM API.
getArtResourceForWeatherCondition() : sets art icons in ListView.
WeatherContract.java : In this file I initialized the Apps databases
columns and Table names.
We are also using this class to define the URIs that the app is using to
access its data.
It contains two inner classes LocationEntry & WeatherEntry which
defines the tables for Location and Weather Tables respectively.
LocationEntry : this class defines the contents of Location db table.
It has following entries :
o TABLE_NAME : table name of the location table.
o COLOUMN_LOCATION_SETTING : String which is sent to the
OWM API as query.
o COLOUMN_CITY_NAME : Human Readable Location String,
provided by the API. Ex: Kanpur, Uttar Pradesh, India etc.
o COLOUMN_COORD_LAT : Latitude of the location.
o COLOUMN_COORD_LON : Longitude of the location.
WeatherEntry : this class defines the contents of Weather db table.
It has following entries :
o TABLE_NAME : table name for storing weather data.
o COLUMN_LOC_KEY : It is the column with foreign key in
Location table containing location id.
o COLUMN_DATE : stored as milliseconds since the epoch.
o COLUMN_WEATHER_ID : weather ID as returned by API, to
identify the Icon.
o COLUMN_SHORT_DESC : description of weather provided by
API. As clear or cloudy etc.
o COLUMN_MIN_TEMP : Minimum temperature of the day. Stored
as float.
o COLUMN_MAX_TEMP : Maximum temperature of the day.
Stored as float.
o COLUMN_HUMIDITY : humidity is stored as float, representing
percentage.
o COLUMN_PRESSURE : pressure is also stored as float,
representing percentage.
o COLUMN_DEGREES : meteorological degrees. 0 is north, 180 is
south.
WeatherDbHelper.java : This file is managing the local database for
weather data. WeatherDbHelper class extends SQLiteOpenHelper to
create and filling in entries into tables.
The databases name given is weather.db .
onCreate() : In this method we are creating queries to build Weather
and Locations table.

final String SQL_CREATE_LOCATION_TABLE = "CREATE TABLE " +


LocationEntry.TABLE_NAME + " (" +
LocationEntry._ID + " INTEGER PRIMARY KEY," +
LocationEntry.COLUMN_LOCATION_SETTING + " TEXT UNIQUE NOT NULL, " +
LocationEntry.COLUMN_CITY_NAME + " TEXT NOT NULL, " +
LocationEntry.COLUMN_COORD_LAT + " REAL NOT NULL, " +
LocationEntry.COLUMN_COORD_LONG + " REAL NOT NULL " +
" );";

final String SQL_CREATE_WEATHER_TABLE = "CREATE TABLE " +


WeatherEntry.TABLE_NAME + " (" +
WeatherEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
WeatherEntry.COLUMN_LOC_KEY + " INTEGER NOT NULL, " +
WeatherEntry.COLUMN_DATE + " INTEGER NOT NULL, " +
WeatherEntry.COLUMN_SHORT_DESC + " TEXT NOT NULL, " +
WeatherEntry.COLUMN_WEATHER_ID + " INTEGER NOT NULL," +
WeatherEntry.COLUMN_MIN_TEMP + " REAL NOT NULL, " +
WeatherEntry.COLUMN_MAX_TEMP + " REAL NOT NULL, " +
WeatherEntry.COLUMN_HUMIDITY + " REAL NOT NULL, " +
WeatherEntry.COLUMN_PRESSURE + " REAL NOT NULL, " +
WeatherEntry.COLUMN_WIND_SPEED + " REAL NOT NULL, " +
WeatherEntry.COLUMN_DEGREES + " REAL NOT NULL, " +
" FOREIGN KEY (" + WeatherEntry.COLUMN_LOC_KEY + ") REFERENCES " +
LocationEntry.TABLE_NAME + " (" + LocationEntry._ID + "), " +
" UNIQUE (" + WeatherEntry.COLUMN_DATE + ", " +
WeatherEntry.COLUMN_LOC_KEY + ") ON CONFLICT REPLACE);";

And then executing these queries using execSQL().

sqLiteDatabase.execSQL(SQL_CREATE_LOCATION_TABLE);
sqLiteDatabase.execSQL(SQL_CREATE_WEATHER_TABLE);

onUpgrade() : Since the database is only cache for the online data
from API therefore, the upgrade policy is to simply drop the table and
then create a new one.
WeatherProvider.java : This class works as a Content Provider for the
App.
A Content Provider works as a wrapper or Insulation between the
Database and App. Other apps can use it to access the database without
knowing that how it is stored. It is also useful when we are trying to change
the Database type from SQLite to a file or Dynamic Runtime data or a
different Database.
When the data is changed ContentProvider is used by SyncAdapters and
CursorLoaders to update and display the data.

ROUGH ARCHITECTURE OF APP DATABASE AND CONTENTPROVIDERS

WeatherProvider is used to read and write to the database.


It is using URIs to query to and from the Database.
URI acts exactly as URLs, URLs are a type (Subset) of URI.
For example: the URI
CONTENT://COM.EXAMPLE.ANDROID.SUNSHINE.APP/WEATHER/208017
Is used to querying the WEATHER for LOCATION 208017 and the content
provider returns cursor containing the database rows of the database.
URIs that the app is supporting are:
WEATHER (DIR) : Writing to the Weather table in database.
CONTENT://COM.EXAMPLE.ANDROID.SUNSHINE.APP/WEATHER
WEATHER_WITH_LOCATION (DIR) : Used to display the main List
of Forecast.
CONTENT://COM.EXAMPLE.ANDROID.SUNSHINE.APP/WEATHER/[LOCA
TION_QUERY]
WEATHER_WITH_LOCATION_AND_DATE (ITEM) : Used to display
the detailed forecast and explaination.
CONTENT://COM.EXAMPLE.ANDROID.SUNSHINE.APP/WEATHER//[LOC
ATION_QUERY]/[DATE]
LOCATION (DIR) : Writing to the Location table in database.
CONTENT://COM.EXAMPLE.ANDROID.SUNSHINE.APP/LOCATION
In WeatherProvider there is a very important function called
buildUriMatcher(), which is used to match the URIs to corresponding
URI type defined above.
static UriMatcher buildUriMatcher() {
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = WeatherContract.CONTENT_AUTHORITY;
matcher.addURI(authority, WeatherContract.PATH_WEATHER, WEATHER);
matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*",
WEATHER_WITH_LOCATION);
matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*/#",
WEATHER_WITH_LOCATION_AND_DATE);
matcher.addURI(authority, WeatherContract.PATH_LOCATION, LOCATION);
return matcher;
}

Also there are functions to query:


query() : Returns a Cursor for the corresponding row for URIs result.
delete() : Delete all rows and return the number of rows deleted.
update() : for updating the database.
bulkInsert() : We are inserting rows in bulk instead of inserting one-
by-one.
The sync package contains the classes which creates background services
and updates then as well as syncs with the content providers and loaders
using SyncAdapters.
SunshineAuthenticator.java : It manages the Authentication to apps
backend service. I have to create it because SyncAdapter requires an
authenticator object. This is only a stub authenticator. Hence we are
returning null in every implemented @ovrerride function of
AbstractAccountAuthenticator interface.

@Override
public Bundle editProperties(
AccountAuthenticatorResponse r, String s) { throw new UnsupportedOperationException();}
@Override
public Bundle addAccount(AccountAuthenticatorResponse r, String s,String s2,String[] strings,
Bundle bundle) throws NetworkErrorException {
return null;
}
@Override
public Bundle confirmCredentials( AccountAuthenticatorResponse r,Account account, Bundle
bundle) throws NetworkErrorException {
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse r,Account account,String s,Bundle
bundle) throws NetworkErrorException {
throw new UnsupportedOperationException();
}
@Override
public String getAuthTokenLabel(String s) { throw new UnsupportedOperationException(); }
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse r,Account account, String s,
Bundle bundle) throws NetworkErrorException {
throw new UnsupportedOperationException();
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse r,Account account, String[] strings)
throws NetworkErrorException {
throw new UnsupportedOperationException();
}
SunshineSyncAdapter.java : It does the work of syncing the data from the
network in the background. This works as SyncManager.
It handles multiple sync requests using SyncAdapters.
Also takes care of other things like checking for Network Connection and
retrying download of the data.
In this class we are regularly querying the data from the API on fixed
intervals and getting data in JSON format.
The Query URL is like
api.openweathermap.org/data/2.5/forecast/daily?q=208017&mode=json&units=metric&
cnt=1&APPID=[MY_OWM_API_KEY]

and the output will be like


{

"city":{

"id":1261638,

"name":"Nawabganj", "coord":{ "lon":80.300003, "lat":26.5 },

"country":"IN",

},

"cod":"200", "message":0.0069, "cnt":1,

"list":[

"dt":1470722400,

"temp":{"day":31.85, "min":28.25, "max":33.41, "night":28.25, "eve":32.81, "morn":31.85 },

"pressure":998.91,

"humidity":86,

"weather":[

{ "id":500, "main":"Rain", "description":"light rain", "icon":"10d" }

],

"speed":3.57,"deg":190, "clouds":32

}
WEATHER FORECAST FOR TODAY
The SyncAdapter has few functions.
getWeatherDataFromJson() : It takes the string representing the
complete forecast in JSON format and pull out the data we need to
construct the Strings needed for display.
This function also inserts the values into the database using a
ContentValues vector and bulkInsert() method.

notifyWeather() : This methods checks any change in data and


notifies of it. It also checks if the enable notifications is checked in
Settings Menu and whether it should give notification or not.
syncImmediately() : Helper mrthod to have the sync adapter Sync
immediately.
addLocation() : Method to handle insertion of a new location in the
database if it does not exists.
configurePeriodicSync() : It is used to schedule the sync adapter
periodic execution.

public static void configurePeriodicSync(Context context, int syncInterval, int flexTime) {


Account account = getSyncAccount(context);
String authority = context.getString(R.string.content_authority);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// we can enable inexact timers in our periodic sync
SyncRequest request = new SyncRequest.Builder().
syncPeriodic(syncInterval, flexTime).
setSyncAdapter(account, authority).
setExtras(new Bundle()).build();
ContentResolver.requestSync(request);
} else {
ContentResolver.addPeriodicSync(account,
authority, new Bundle(), syncInterval);
}
}

CONFIGUREPERIODICSYNC() FUNCTION
private void getWeatherDataFromJson(String forecastJsonStr,String locationSetting)
throws JSONException {
final String OWM_CITY = "city",OWM_CITY_NAME = "name",OWM_COORD = "coord",OWM_LATITUDE = "lat";
final String OWM_LONGITUDE = "lon",OWM_LIST = "list",OWM_PRESSURE = "pressure",OWM_HUMIDITY = "humidity";
final String OWM_WINDSPEED = "speed",OWM_WIND_DIRECTION = "deg",OWM_TEMPERATURE = "temp";
final String OWM_MAX = "max",String OWM_MIN = "min",OWM_WEATHER =
"weather",OWM_DESCRIPTION="main",OWM_WEATHER_ID = "id";
try {
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
JSONObject cityJson = forecastJson.getJSONObject(OWM_CITY);
String cityName = cityJson.getString(OWM_CITY_NAME);
JSONObject cityCoord = cityJson.getJSONObject(OWM_COORD);
double cityLatitude = cityCoord.getDouble(OWM_LATITUDE);
double cityLongitude = cityCoord.getDouble(OWM_LONGITUDE);
long locationId = addLocation(locationSetting, cityName, cityLatitude, cityLongitude);
Vector<ContentValues> cVVector = new Vector<ContentValues>(weatherArray.length());
Time dayTime = new Time();
dayTime.setToNow();
int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff);
dayTime = new Time();
for(int i = 0; i < weatherArray.length(); i++) {
long dateTime;double pressure;int humidity;double windSpeed;double windDirection;
double high, low; Sring description;int weatherId;
JSONObject dayForecast = weatherArray.getJSONObject(i);
dateTime = dayTime.setJulianDay(julianStartDay+i);
pressure = dayForecast.getDouble(OWM_PRESSURE);
humidity = dayForecast.getInt(OWM_HUMIDITY);
windSpeed = dayForecast.getDouble(OWM_WINDSPEED);
windDirection = dayForecast.getDouble(OWM_WIND_DIRECTION);
JSONObject weatherObject =
dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
description = weatherObject.getString(OWM_DESCRIPTION);
weatherId = weatherObject.getInt(OWM_WEATHER_ID);
JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE);
high = temperatureObject.getDouble(OWM_MAX);
low = temperatureObject.getDouble(OWM_MIN);
ContentValues weatherValues = new ContentValues();
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_LOC_KEY, locationId);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DATE, dateTime);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_HUMIDITY, humidity);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_PRESSURE, pressure);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WIND_SPEED, windSpeed);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DEGREES, windDirection);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, high);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MIN_TEMP, low);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_SHORT_DESC, description);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, weatherId);
cVVector.add(weatherValues);
}
int inserted = 0;
if ( cVVector.size() > 0 ) {
ContentValues[] cvArray = new ContentValues[cVVector.size()];
cVVector.toArray(cvArray);
getContext().getContentResolver().bulkInsert(WeatherContract.WeatherEntry.CONTENT_URI, cvArray);
getContext().getContentResolver().delete(WeatherContract.WeatherEntry.CONTENT_URI,
WeatherContract.WeatherEntry.COLUMN_DATE + " <= ?",
new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))});
notifyWeather();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
FUNCTION GETWEATHERDATAFROMJSON()
SunshineAuthenticatorService.java : This class is a service which lets
the sync adapter to access the authenticator.

public class SunshineAuthenticatorService extends Service {


// Instance field that stores the authenticator object
private SunshineAuthenticator mAuthenticator;

@Override
public void onCreate() {
// Create a new authenticator object
mAuthenticator = new SunshineAuthenticator(this);
}

@Override
public IBinder onBind(Intent intent) {
return mAuthenticator.getIBinder();
}
}

SunshineSyncService.java : It is the service which runs the sync adapter


in the background.

public class SunshineSyncService extends Service {


private static final Object sSyncAdapterLock = new Object();
private static SunshineSyncAdapter sSunshineSyncAdapter = null;

@Override
public void onCreate() {
synchronized (sSyncAdapterLock) {
if (sSunshineSyncAdapter == null) {
sSunshineSyncAdapter = new SunshineSyncAdapter(getApplicationContext(), true);
}
}
}

@Override
public IBinder onBind(Intent intent) {
return sSunshineSyncAdapter.getSyncAdapterBinder();
}
}

Das könnte Ihnen auch gefallen