14. 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
16. 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();
17. Show dummy Data
for (String toyName : toyNames) {
mToysListTextView.append(toyName + "nnn");
}
--------------- or ---------------
for (int i = 0; i<toyNames.lenght; i++) {
mToysListTextView.append(toyNames[i] + "nnn");
}
43. 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
57. 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
60. 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
61. 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
63. My Way
1. Tambahkan pada Constructor Adapter
(int[] data, Context context)
2. Sehingga saat manggil Adapter jadi Adapter(dataAngka,this);
3. holder.cardview.setOnClickLister
68. 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
69. Implisit Intent
Intent pindah =
new Intent (MainActivity.this, TujuanActivity.class);
context , class tujuan
startActivity(pindah);
70. PutExtra
Intent pindah =
new Intent (MainActivity.this, TujuanActivity.class)
pindah.putExtra(“key1”,”value1”);
pindah.putExtra(“key2”,2);
startActivity(pindah);
80. 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
100. 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)
103. How to Input
SharedPreferences pref =
getApplicationContext().getSharedPreferences("MyChar", 0);
SharedPreferences.Editor editor = pref.edit();
editor.putString("KEY", “VALUE”);
editor.commit();
104. How to Get
SharedPreferences pref =
getApplicationContext().getSharedPreferences("MyChar", 0);
String karakter = pref.getString("KEY", “Default Value”);
112. 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
122. 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
123. 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;
125. 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);
126. 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;
127. 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;
129. 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";
...
...
130. 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";
}
}
132. 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);
}
133. 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);
}
161. 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";
}
}
166. 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;
}
173. 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;
}
174. 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;
175. 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);
193. 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
196. 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;
}
209. 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" />
210. 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);
224. 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
225. 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.
226. 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.
227. 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.