Sunteți pe pagina 1din 229

Android

Intermediate
Ahmad Arif Faizin
What will we learn?
- Building UI (Responsive Design)
- AsyncTask (JSON Parsing)
- RecyclerView
- Intent
- Lifecycle
- Preferences
- SQLite
- Content Provider
- Background Task (Notification & Sync)
“ The master has failed
more times than the


beginner has even tried.
Sunshine Project Exercise

Sunshine Project
https://github.com/udacity/ud851-Sunshine

Toys Project
https://github.com/udacity/ud851-Exercises
Flow

1. Impot.ExerciseProject();
2. Shift*2 (TODO);
3. for (i=0; i<TODO.size();i++){TODO.execute();}
4. while (!Succed){try();}
5. Import.NextExerciseProject
LESSON 1
Make Sunshine Project
Exercise 1 - Create Layout
Exercise 1.1 - Create Layout
Flow
Flow
Exercise 1.2 - DisplayToyList
Add an ID

@ sebagai pembeda bahwa itu bukan String, tapi untuk


mencari/menambahkan isi di dalam Resource

+ sebagai tanda bahwa untuk menambahkan id baru, bukan


untuk mencari

tv_tv_names : nama id dalam bentuk Snake Case


CamelCase snake_case
Make array of String
1. Create New JavaClass “ToyBox.java”
2. public static String[] getToyNames() {
return new String[] {
"Tazos",
“...........”
};
}
3. Panggil dalam MainActivity
String[] toyNames = ToyBox.getToyNames();
Show dummy Data
for (String toyName : toyNames) {
mToysListTextView.append(toyName + "\n\n\n");
}
--------------- or ---------------

for (int i = 0; i<toyNames.lenght; i++) {


mToysListTextView.append(toyNames[i] + "\n\n\n");
}
Make dummy Data

teks.SetText(“Halo”); teks.append(“Halo”);
teks.SetText(“Akhirat”); teks.append(“Akhirat”);
Output : Output :
“Akhirat” “HaloAkhirat”
Exercise 1.3 - Add Scrolling View
NOW IS YOUR
TIME...
>>Create Layout Sunshine Project
S.01-01
S.01-02
S.01-03
LESSON 2
Connect to Internet
Logging

Log.d(“string key”,”string isi”);

Log.e --> Error


Log.w --> Warning
Log.e --> Info
Log.d --> Debug
Log.v --> Verbose
T02.01-
Exercise-CreateLayout
T02.02-Exercise-AddMenu

- Buat resource “Menu”


- Add MenuItem
- Override onCreateOptionMenu kemudian inflate MenuItem
- Override onOptionItemSelected untuk EventHandling
T02.03-Exercise-DisplayUrl

https://api.github.com/search/repositories?q=android
&sort=stars
Make URLHTTP Request
T02.04-Exercise-
ConnectingToTheInternet
Add Permission
<uses-permission android:name="android.permission.INTERNET"/>

Then try to Run It..


NetworkOnMainThread
Exception
NetworkOnMainThread
Exception
Akses Network tidak boleh di Main Thread
T02.05-
Exercise-CreateAsyncTask
T02.06-
Exercise-AddPolish
- Check if there is no connection
- Add progress bar
JSON FORMAT
Example of JSON Format
JSON Format
Use https://jsonlint.com/ or https://jsonformatter.curiousconcept.com/

JSON Object
{ "key" : value}

JSON Array
[value, value, value]
EXAMPLE OF JSON FORMAT
NOW IS YOUR
TIME...
>>Create Networking
Get API Key
Get Open Weather API Key
https://www.openweathermap.org/appid

Example Query:
http://api.openweathermap.org/data/2.5/forecast/daily?q=ambarawa&
mode=json&units=metric&cnt=7&APPID=93a3696714297ee5a9f6548
6aa8cb824

Supaya rapi pakai JSON Formatter / JSON Linter


S02.01-Exercise-Networking
S02.02-Exercise-Menus
S02.03-Exercise-Polish
Other Solution :
Library for HTTP Request

Source : http://stackoverflow.com/questions/16902716/comparison-of-android-
networking-libraries-okhttp-retrofit-and-volley
LESSON 3
RecyclerView
UI Evolution
UI Evolution
RecyclerView

Nice References ;
https://wirasetiawan29.wordpress.com/2016/03/04/viewholder-di-android/
https://medium.com/@ocittwo/recyclerview-dan-adapternya-ce6332a0833
RecyclerView vs ListView
+ ViewHolder Pattern
+ LayoutManager (Linear, Grid, Staggered)
+ Item animators and item decorators
+ More explicit click listeners
Quiz
Quiz Answer
RecyclerView

LinearLayoutManager GridLayoutManager StaggeredLayoutManager

Source :
https://medium.com/@ocittwo/recyclerview-dan-adapternya-ce6332a0833
T03.01-
Exercise-RecyclerViewLayout
1. Add Dependency in build.gradle(Module:app) >sync now
compile 'com.android.support:recyclerview-v7:25.3.1'
2. Add RecyclerView in xml with ID
T03.02-
Exercise-ViewHolder
1. Add Dependency in build.gradle(Module:app) >sync now
compile 'com.android.support:recyclerview-v7:25.3.1'
2. Add RecyclerView in xml with ID
3. Add item_list.xml design
4. Add Adapter.java
Make ViewHolder Class extends RecyclerView.ViewHolder
RecyclerView

Source :
https://medium.com/@ocittwo/recyclerview-dan-adapternya-ce6332a0833
RecyclerView

Source :
https://medium.com/@ocittwo/recyclerview-dan-adapternya-ce6332a0833
T03.03-
Exercise-RecyclerViewAdapter
4. Add Adapter.java
- Make ViewHolder Class extends RecyclerView.ViewHolder
- Make Adapter Class Extends
RecylerView.Adapter<RecyclerView.ViewHolder>
- Implement method
- onCreateViewHolder > untuk inflate layout_item
- onBindViewHolder > untuk proses tiap-tiap komponen
- getItemCount > jumlah list data
T03.04-Exercise-
WiringUpRecyclerView
1. Add Dependency in build.gradle(Module:app) >sync now
compile 'com.android.support:recyclerview-v7:25.3.1'
2. Add RecyclerView in xml with ID
3. Add item_list.xml design
4. Add Adapter.java then setAdapter
5. Add LayoutManager then setLayoutManager
T03.07-Exercise-
RecyclerViewClickHandling
1. Make ListItemClickListener
2. Implement OnClickListener in ViewHolder
My Way
1. Tambahkan pada Constructor Adapter
(int[] data, Context context)
2. Sehingga saat manggil Adapter jadi Adapter(dataAngka,this);
3. holder.cardview.setOnClickLister
NOW IS YOUR
TIME...
>>Create RecyclerView
S03.01-Exercise-RecyclerView
S03.02-Exercise-ClickHandling
LESSON 4
Intent
New Activity

Create Activity
Klik kanan pada package > new > activity > blank activity > OK

Change Launcher Activity


Move <intent-filter> in Android Manifest ke Activity yg pertama
Implisit Intent

Intent pindah =
new Intent (MainActivity.this, TujuanActivity.class);
context , class tujuan
startActivity(pindah);
PutExtra

Intent pindah =
new Intent (MainActivity.this, TujuanActivity.class)
pindah.putExtra(“key1”,”value1”);
pindah.putExtra(“key2”,2);
startActivity(pindah);
GetExtra

String data1 = getIntent().getStringExtra(“key1”);


String data1 = getIntent().getIntExtra(“key2”);
Explisit Intent
Intent.ACTION_DIAL/Intent.ACTION_CALL
Intent.ACTION_SEARCH
Intent.ACTION_SEND
Intent.ACTION_VIEW
Intent.ACTION_OPEN_DOCUMENT
AlarmClock.ACTION_SET_ALARM
MediaStore.ACTION_IMAGE_CAPTURE
More : https://developer.android.com/guide/components/intents-common.html
Intent Share
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_SUBJECT, "ID-Networkers");
share.putExtra(Intent.EXTRA_TEXT, "http://idn.id");
startActivity(Intent.createChooser(share, "Share link!"));
Send to Frgament
NOW IS YOUR
TIME...
>>Create RecyclerView
S04.01-LaunchNewActivity
S04.02-DisplayDayForecast.
S04.03-AddMapAndSharing.
LESSON 5
LifeCycle
Get Data from API

http://openweathermap.org/appid

Example of API Request


http://api.openweathermap.org/data/2.5/forecast/daily?
q=ambarawa&mode=json&units=metric&cnt=7
&APPID=93a3696714297ee5a9f65486aa8cb824
Try to Rotate
Your App!
What happen?
T05a.01-Exercise-LogLifecycle
T05a.02-Exercise-PersistData
Save to instanceState
- Override Method onSaveInstanceState
- outstate.putString(“KEY”, “VALUE”);
di onCreate
- if (savedInstanceStated != null) {
String DataSimpanan = savedInstanceState.getString(“KEY”);
}
AsynctaskLoader
3 STEPS TO USE LOADER
T05a.02-Exercise-PersistData
Save to instanceState
https://classroom.udacity.com/courses/ud851/lessons/ed13cc93-
2861-43bf-b7ed-395a166ab975/concepts/29dfb358-58ec-4364-
8f1d-74488de38424
Why AsynctaskLoader?
T05b.02 -AddAsyncTaskLoader
T05b.03-PolishAsyncTask
Tips ketika di-rotate tetep
Manifest
android:configChanges="orientation|screenSize"
Activity
@Override
public void onConfigurationChanged(Configuration
newConfig) {
super.onConfigurationChanged(newConfig);
}
NOW IS YOUR
TIME...
>>Create RecyclerView
S05.01-Exercise-AsyncTaskLoader
LESSON 6
Preferences
SharedPreferences

- Used for save setting

Format
”Key”,”Value”
T06.01-SetupTheActivity
T06.02-PreferenceFragment
How to use

Method 1
public static final String PREFS_NAME = "AOP_PREFS";
SharedPreferences pref= getSharedPreferences(PREFS_NAME,
Context.MODE_PRIVATE);
Method 2
SharedPreferences pref=
PreferenceManager.getDefaultSharedPreferences(context)
How to Use
How to Use
How to Input
SharedPreferences pref =
getApplicationContext().getSharedPreferences("MyChar", 0);

SharedPreferences.Editor editor = pref.edit();


editor.putString("KEY", “VALUE”);
editor.commit();
How to Get
SharedPreferences pref =
getApplicationContext().getSharedPreferences("MyChar", 0);
String karakter = pref.getString("KEY", “Default Value”);
>>Best Practice

Use @string / Constanta


for Key
T06.03-GetSharedPreferences
How to Get
How to Get
>>Best Practice

Use @string / Constanta


for Key
>>Best Practice

Use @string / Constanta


for Key
>>Best Practice

Use @string / Constanta


for Key
PR 2
- Model
- JSON
- Intent Kirim Data :
thumbnail gambar poster film
plot sinopsis (melalui pemanggilan overview di api)
rating pengguna (melalui pemanggilan vote_average di api)
tanggal rilis
T06.05-PreferenceChangeListener
How to Get
How to Get
public boolean onPreferenceChange(Preference preference, Object newValue) {
Toast error = Toast.makeText(getContext(), "Please select a number between 0.1 and 3", Toast.LENGTH_SHORT);

String sizeKey = getString(R.string.pref_size_key);


if (preference.getKey().equals(sizeKey)) {
String stringSize = ((String) (newValue)).trim();
if (stringSize.equals("")) stringSize = "1";
try {
float size = Float.parseFloat(stringSize);
if (size > 3 || size <= 0) {
error.show();
return false;
}
} catch (NumberFormatException nfe) {
error.show();
return false;
}
}
return true;
}
NOW IS YOUR
TIME...
>>Create RecyclerView
S06.01-LaunchSettingsActivity
S06.02-SettingsFragment
S06.03-PolishingPreferences
LESSON 7
SQLite
LESSON 7
SQLite
Save it Offline!

+User Experience (Not waiting loading with Blank Screen)


+Battery Life
+Saving quota
+Reduce server load and network bandwith
+Run without internet connection area
Basic Database
Create TABLE
CREATE TABLE weather( _id INTEGER PRIMARY KEY, date TEXT
NOT NULL, min REAL NOT NULL, max REAL NOT NULL,
humidity REAL NOT NULL, pressure REAL NOT NULL);

Delete TABLE
DROP TABLE weather;
Basic Database
Basic Database
Insert row into TABLE
INSERT INTO weather VALUES(2,'20140626',17,21,0,1031);
INSERT INTO weather VALUES(3,'20140627',18,22,0,1055);
INSERT INTO weather VALUES(4,'20140628',18,21,10,1070);
Basic Database
Show Data from TABLE
SELECT * FROM weather;
SELECT * FROM weather WHERE date == 20140626;
SELECT _id,date,min,max FROM weather WHERE date >
20140625 AND date < 20140628;
SELECT * FROM weather WHERE min >= 18 ORDER BY max
ASC;
Basic Database
Update row in TABLE
UPDATE weather SET min = 0, max = 100 where date >=
20140626 AND date <= 20140627;

Delete row in TABLE


DELETE FROM weather WHERE humidity != 0;
Basic Database
INNER JOIN
https://en.wikipedia.org/wiki/Join_(SQL)#Inner_join

Delete row in TABLE


DELETE FROM weather WHERE humidity != 0;
WeatherContract.java

public static final String TABLE_NAME = "weather";


public static final String COLUMN_LOC_KEY = "location_id";
public static final String COLUMN_DATE = "date";
...
...
Contract

public class MovieContract {


public static final class MovieEntry implements BaseColumns {
//untuk sqlite
public static final String TABLE_NAME = "movie";
public static final String COLUMN_ID = "id";
public static final String COLUMN_JUDUL = "title";
public static final String COLUMN_POSTER = "poster_path";

}
}
Basic Database
SQLiteDbHelper

public class MovieDbHelper extends SQLiteOpenHelper {


public static final String DATABASE_NAME = "film.db";
private static final int DATABASE_VERSION = 1;

public MovieDbHelper(Context context) {


super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
SQLiteDbHelper
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
final String SQL_CREATE_WEATHER_TABLE =
"CREATE TABLE " + MovieContract.MovieEntry.TABLE_NAME + " (" +
MovieContract.MovieEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
MovieContract.MovieEntry.COLUMN_ID + " INTEGER NOT NULL, " +
MovieContract.MovieEntry.COLUMN_JUDUL + " TEXT NOT NULL, " +
MovieContract.MovieEntry.COLUMN_POSTER + " TEXT NOT NULL, " +
"UNIQUE (" + MovieContract.MovieEntry.COLUMN_JUDUL + ") ON CONFLICT REPLACE);";
sqLiteDatabase.execSQL(SQL_CREATE_WEATHER_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + MovieContract.MovieEntry.TABLE_NAME);
onCreate(sqLiteDatabase);
}
How to Use SQLite
T07.04-Exercise-
UpdateTheAdapter
NOW IS YOUR
TIME...
>>Create Database
LESSON 8
Content Provider
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
LESSON 9
Create Content Provider
Basic Database
Basic Database
1. Create ContentProvider Class
public class FilmContentProvider extends ContentProvider {

MovieDbHelper dbHelper;
@Override
public boolean onCreate() {
Context context = getContext();
dbHelper = new MovieDbHelper(context);
return true;
}

.
.
.
.
Basic Database
Basic Database
2. Android Manifest
<application>
.
.
.
.
<provider
android:name=".data.MovieContentProvider"
android:authorities="id.co.imastudio.popmov"
android:exported="false" />
</application>
Basic Database
Basic Database
3. DefineURI
ALL FILM
content://id.co.imastudio.recyclerview/listfilm

FILM WITH ID
content://id.co.imastudio.recyclerview/listfilm/#
Basic Database
Basic Database
4. Create URI
public class MovieContract {
public static final String AUTHORITY = "id.co.imastudio.popmov";
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
public static final String PATH_TASKS = "listfilm";

public static final class MovieEntry implements BaseColumns {


//Untuk Uri
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendPath(PATH_TASKS).build();
//untuk sqlite
public static final String TABLE_NAME = "movie";
public static final String COLUMN_ID = "id";
public static final String COLUMN_JUDUL = "title";
public static final String COLUMN_POSTER = "poster_path";
}
}
Basic Database
Basic Database
Basic Database
Basic Database
5. Build URI Matcher
//2 membuat Uri Matcher
public static final int ALL_FILM = 100;
public static final int FILM_WITH_ID = 101;

private static final UriMatcher sUriMatcher = buildUriMatcher();

public static UriMatcher buildUriMatcher() {

UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI(MovieContract.AUTHORITY, MovieContract.PATH_TASKS, ALL_FILM);


uriMatcher.addURI(MovieContract.AUTHORITY, MovieContract.PATH_TASKS + "/#", FILM_WITH_ID);

return uriMatcher;
}
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
MovieContentProvider-Query
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[]
selectionArgs, @Nullable String sortOrder) {
final SQLiteDatabase db = dbHelper.getReadableDatabase();
int match = sUriMatcher.match(uri);
Cursor retCursor;
switch (match) {
case ALL_FILM:
retCursor = db.query(MovieContract.MovieEntry.TABLE_NAME,
projection, selection, selectionArgs, null, null, sortOrder);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
MovieContentProvider-Insert
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
final SQLiteDatabase db = dbHelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
Uri returnUri; // URI to be returned
switch (match) {
case ALL_FILM:
long id = db.insert(MovieContract.MovieEntry.TABLE_NAME, null, contentValues);
if ( id > 0 ) {
returnUri = ContentUris.withAppendedId(MovieContract.MovieEntry.CONTENT_URI, id);
} else {
throw new android.database.SQLException("Failed to insert row into " + uri);
}
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return returnUri;
MovieContentProvider-Delete
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
final SQLiteDatabase db = dbHelper.getWritableDatabase();
int numRowsDeleted;
if (null == selection) selection = "1";
switch (sUriMatcher.match(uri)) {
case ALL_FILM:
numRowsDeleted = dbHelper.getWritableDatabase().delete(
MovieContract.MovieEntry.TABLE_NAME,
selection,
selectionArgs);
db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + MovieContract.MovieEntry.TABLE_NAME + "'");
break;
case FILM_WITH_ID:
numRowsDeleted = db.delete(MovieContract.MovieEntry.TABLE_NAME, MovieContract.MovieEntry.COLUMN_ID + " = ?",
new String[]{String.valueOf(ContentUris.parseId(uri))});
db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + MovieContract.MovieEntry.TABLE_NAME + "'");
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
Insert Database
private void tambahkedatabase() {
ContentValues cv = new ContentValues();
cv.put(MovieContract.MovieEntry.COLUMN_ID, dataId);
cv.put(MovieContract.MovieEntry.COLUMN_JUDUL, dataJudul);
cv.put(MovieContract.MovieEntry.COLUMN_POSTER, dataPoster);
Log.d(TAG, "onResponse: "+ cv.get(MovieContract.MovieEntry.COLUMN_POSTER));
Uri uri = getContentResolver().insert(MovieContract.MovieEntry.CONTENT_URI, cv);
Toast.makeText(DetailActivity.this, "Uri :" + uri, Toast.LENGTH_SHORT).show();

}
Delete Database
private void hapusdaridatabase() {

getContentResolver().delete(MovieContract.MovieEntry.CONTENT_URI.buildUpon().appendPath(String.va
lueOf(dataId)).build(), null, null);

}
Basic Database
Basic Database
Basic Database
Basic Database
Using Loader to Load Data
getSupportLoaderManager().initLoader(ID_FILM_LOADER, null, this);
-----
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
switch (loaderId) {
case ID_FILM_LOADER:
Uri forecastQueryUri = FilmContract.FilmEntry.CONTENT_URI;
return new CursorLoader(this, forecastQueryUri, null, null, null, null);
default:
throw new RuntimeException("Loader Not Implemented: " + loaderId);
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(data.getCount()>0) {
initAdapter(getMoviesFromCursor(data));
} else {
Toast.makeText(getActivity(), "Tidak Ada Favorite", Toast.LENGTH_LONG).show();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
getMoviesFromCursor
private ArrayList<MovieModel> getMoviesFromCursor(Cursor cursor) {
ArrayList<MovieModel> movies = new ArrayList<>();

if (cursor != null) {
/*Log.e("cursor length","->"+cursor.getCount());
Log.e("column length","->"+cursor.getColumnCount());*/
if (cursor.moveToFirst()){
do{
MovieModel movie = new MovieModel();
movie.setId(cursor.getInt(cursor.getColumnIndex(MovieContract.MovieEntry.COLUMN_ID)));
movie.setJudul(cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.COLUMN_JUDUL)));
movie.setPoster(cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.COLUMN_POSTER)));
movies.add(movie);
}while(cursor.moveToNext());
}
}
return movies;
}
LESSON 10
Background Task
Notification
private NotificationManager mNotifyManager;
private int NOTIFICATION_ID = 0;
----
//dalam onCreate
mNotifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
----
private void tampilinNotification() {

NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)


.setContentTitle("New Notification!")
.setContentText("Favorite berhasil ditambah.")
.setSmallIcon(R.drawable.ic_action_notif)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
//harus v4
Notification myNotification = notifyBuilder.build();
mNotifyManager.notify(NOTIFICATION_ID, myNotification);

}
Notification + Intent Masuk App
private void tampilinNotification() {

//masuk aplikasi
Intent notificationIntent = new Intent(this, TabActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)


.setContentTitle("New Notification!")
.setContentText("Favorite berhasil ditambah.")
.setSmallIcon(R.drawable.ic_action_notif)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setContentIntent(notificationPendingIntent);
//harus v4
Notification myNotification = notifyBuilder.build();
mNotifyManager.notify(NOTIFICATION_ID, myNotification);

}
Notification + Action View Intent
private void tampilinNotification() {

//masuk web
Intent learnMoreIntent = new Intent(Intent.ACTION_VIEW, Uri
.parse("http://www.idn.id"));
PendingIntent learnMorePendingIntent = PendingIntent.getActivity
(this,NOTIFICATION_ID,learnMoreIntent,PendingIntent.FLAG_ONE_SHOT);

NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)


.setContentTitle("New Notification!")
.setContentText("Favorite berhasil ditambah.")
.setSmallIcon(R.drawable.ic_action_notif)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.addAction(R.drawable.ic_info_black_24dp,"Learn More", learnMorePendingIntent);
//harus v4
Notification myNotification = notifyBuilder.build();
mNotifyManager.notify(NOTIFICATION_ID, myNotification);
Update Notification + BigPicture
private void updatenotification() {
Intent notificationIntent = new Intent(this, TabActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Bitmap androidImage = BitmapFactory


.decodeResource(getResources(),R.drawable.film);

NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)


.setContentTitle("Update Notification!")
.setContentText("Favorite dihapus.")
.setSmallIcon(R.drawable.ic_action_notif)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"))
.setContentIntent(notificationPendingIntent);
//harus v4
Notification myNotification = notifyBuilder.build();
mNotifyManager.notify(NOTIFICATION_ID, myNotification);
Notification + Action Update
private static final String ACTION_UPDATE_NOTIFICATION ="id.co.imastudio.popmov.ACTION_UPDATE_NOTIFICATION";

----

private void tampilinNotification() {


//action
Intent updateintent = new Intent(ACTION_UPDATE_NOTIFICATION);
PendingIntent updatePendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, updateIntent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Notification!")
.setContentText("Favorite berhasil ditambah.")
.setSmallIcon(R.drawable.ic_action_notif)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.addAction(R.drawable.ic_sync_black_24dp, "Update", deletePendingIntent);
//harus v4
Notification myNotification = notifyBuilder.build();
mNotifyManager.notify(NOTIFICATION_ID, myNotification);
}
Receive Action Update
private NotificationReceiver mReceiver = new NotificationReceiver();
---
//dalam onCreate
registerReceiver(mReceiver,new IntentFilter(ACTION_UPDATE_NOTIFICATION));
---
public class NotificationReceiver extends BroadcastReceiver {
public NotificationReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case ACTION_UPDATE_NOTIFICATION:
updatenotification();
}
}
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
Alarm Manager
private AlarmManager alarmManager;
---
//dalam onCreate
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
---
private void buatJadwalAlarm() {
Intent notificationIntent = new Intent(this, MyAlarmReceiver.class);
PendingIntent notifyPendingIntent = PendingIntent.getBroadcast(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

long triggerTime = SystemClock.elapsedRealtime()


+ AlarmManager.INTERVAL_FIFTEEN_MINUTES;
long repeatInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES;

//If the Toggle is turned on, set the repeating alarm with a 15 minute interval
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerTime, repeatInterval, notifyPendingIntent);
}
Alarm Manager Check
boolean alarmUp = (PendingIntent.getBroadcast(this, NOTIFICATION_ID, notificationIntent,
PendingIntent.FLAG_NO_CREATE) != null);

if (alarmUp){
Log.d(TAG, "setInexactRepeatingAlarm: Alarm tiap 30 detik nyala");
}
Make AlarmReceiver
1. Create New > Other > Receiver

<receiver
android:name=".MyAlarmReceiver"
android:enabled="true"
android:exported="false">
</receiver>

2. hapus throw new exception


3. Buat notifikasi contentintent di dalam onReceive
AlarmReceiver
public class MyAlarmReceiver extends BroadcastReceiver{
private int NOTIFICATION_ID = 1;
@Override
public void onReceive(Context context, Intent intent) {
NotificationManager mNotifyManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
//masuk aplikasi
Intent notificationIntent = new Intent(context, TabActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(context,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(context)
.setContentTitle("Sudah 15 menit!")
.setContentText("Cek aplikasinya.")
.setSmallIcon(R.drawable.ic_action_notif)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true)
.setContentIntent(notificationPendingIntent);
//harus v4
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
}
}
Job Scheduler
private JobScheduler mScheduler;
private int JOB_ID = 21;
---
//dalam onCreate
mScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
scheduleJob();
---
private void scheduleJob() {
ComponentName serviceName = new ComponentName(getPackageName(),
NotificationJobService.class.getName());
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceName);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
builder.setRequiresCharging(true);
builder.setPeriodic(86400000);

JobInfo myJobInfo = builder.build();


mScheduler.schedule(myJobInfo);

Toast.makeText(DetailActivity.this, "ScheduleJob has been running", Toast.LENGTH_SHORT).show();


}
NotificationJobService
public class NotificationJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
//Set up the notification content intent to launch the app when clicked
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainScreen.class),
PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)


.setContentTitle("JobService Coming")
.setContentText("Yeayy, just be happy, this only show when baterry charged")
.setContentIntent(contentPendingIntent)
.setSmallIcon(R.drawable.ic_home_black_24dp)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true);
manager.notify(0, builder.build());
Log.d(TAG, "onStartJob: called");
return false;
}
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
Basic Database
FilmSyncTask
public class FilmSyncTask {

synchronized public static void syncFilm(final Context context) {

// isi buat update data

}
}
FilmIntentService
public class FilmIntentService extends IntentService {
public FilmIntentService() {
super("FilmIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
FilmSyncTask.syncFilm(this);
}
}
---------- Manifest
<service
android:name=".sync.FilmIntentService"
android:exported="false" />
FilmSyncUtils
public class FilmSyncUtils {

public static void startImmediateSync(@NonNull final Context context) {


Intent intentToSyncImmediately = new Intent(context, FilmIntentService.class);
context.startService(intentToSyncImmediately);
}
}

----

FilmSyncUtils.startImmediateSync(this);
Basic Database
Basic Database
FilmFirebaseJobService
public class FilmFirebaseJobService extends JobService {
private AsyncTask<Void, Void, Void> mFetchWeatherTask;
@Override
public boolean onStartJob(final JobParameters jobParameters) {
mFetchWeatherTask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
Context context = getApplicationContext();
FilmSyncTask.syncFilm(context);
<service
return null;
android:name=".sync.FilmFirebaseJobService"
}
android:exported="false">
@Override
<intent-filter>
protected void onPostExecute(Void aVoid) {
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
jobFinished( jobParameters, false);
</intent-filter>
}
</service>
};
mFetchWeatherTask.execute();
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
if (mFetchWeatherTask != null) {
mFetchWeatherTask.cancel(true);
}
return true;
}
}
FilmFirebaseJobService
static void scheduleFirebaseJobDispatcherSync(@NonNull final Context context) { private static final int SYNC_INTERVAL_HOURS = 3;
private static final int SYNC_INTERVAL_SECONDS = (int)
Driver driver = new GooglePlayDriver(context); TimeUnit.HOURS.toSeconds(SYNC_INTERVAL_HOURS);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver); private static final int SYNC_FLEXTIME_SECONDS =
SYNC_INTERVAL_SECONDS / 3;
Job syncSunshineJob = dispatcher.newJobBuilder() private static boolean sInitialized;
.setService(FilmFirebaseJobService.class) private static final String SUNSHINE_SYNC_TAG =
.setTag(SUNSHINE_SYNC_TAG) "sunshine-sync";
.setConstraints(Constraint.ON_ANY_NETWORK)
.setLifetime(Lifetime.FOREVER)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(
SYNC_INTERVAL_SECONDS,
SYNC_INTERVAL_SECONDS + SYNC_FLEXTIME_SECONDS))
.setReplaceCurrent(true)
.build();

dispatcher.schedule(syncSunshineJob);
}
Notification Manager
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
.setColor(ContextCompat.getColor(context, R.color.colorPrimary))
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("Data Film Anyar")
.setContentText("didelok gan!")
.setAutoCancel(true);

Intent detailIntentForToday = new Intent(context, MainActivity.class);

TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);


taskStackBuilder.addNextIntentWithParentStack(detailIntentForToday);
PendingIntent resultPendingIntent = taskStackBuilder
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

notificationBuilder.setContentIntent(resultPendingIntent);

NotificationManager notificationManager = (NotificationManager)


context.getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(12234, notificationBuilder.build());
Notification Manager
Notification Manager
Notification Manager
Notification Manager
Notification Manager
Notification Manager
Notification Manager
FINAL PROJECT
Let's do it!
Final Project
- Grid Layout
- Sort by Popular , Top Rated, and Favorit
- Detail Screen (title, release date, movie poster, vote average,
and plot synopsis, trailer, and review)
- Mark it as a Favorite.
- Networking in background thread
- Content provider to save Favorit offline
Final Project
save app state and restores it via
onSaveInstanceState/onRestoreInstanceState.
For example,
When a list item is selected, it remains selected on rotation.
When an activity is displayed, the same activity appears on
rotation.
User text input is preserved on rotation.
Maintains list items positions on device rotation.
Final Project
You must make sure your app does not crash when there is no
network connection! You can see this StackOverflow post on
how to do this. If your app crashes when there is no network
connection, you will not pass the project.
Final Project ++
++
+Extend the favorites ContentProvider to store the movie
poster, synopsis, user rating, and release date, and display them
even when offline.
+ Implement sharing functionality to allow the user to share the
first trailer’s YouTube URL from the movie details screen.
Final Project
https://docs.google.com/document/d/1ZlN1fUsCSKuInLECcJkslI
qvpKlP7jWL2TP9m6UiA6I/pub?embedded=true#h.7sxo8jefdfll

http://stackoverflow.com/questions/1560788/how-to-check-
internet-access-on-android-inetaddress-never-times-out
From : Ambarawa
Phone : 085740482440
About Me
FB : fb.me/faizinarif
Instagram : arif_faizin
Github : github.com/arifaizin
Education :
• SDN Kupang 01 Ambarawa
• SMPN 2 Paciran Lamongan / PPSD
• SMAN 1 Ambarawa Ahmad
• Universitas Diponegoro
• Pesantren Programmer ARIF
Now :
IMASTUDIO SEMARANG Faizin
IMAKIDZ

S-ar putea să vă placă și