├── .gitignore
├── .idea
├── caches
│ └── build_file_checksums.ser
├── codeStyles
│ └── Project.xml
├── gradle.xml
├── misc.xml
└── runConfigurations.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── codingwithmitch
│ │ └── notes
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── codingwithmitch
│ │ │ └── notes
│ │ │ ├── LinedEditText.java
│ │ │ ├── NoteActivity.java
│ │ │ ├── NotesListActivity.java
│ │ │ ├── adapters
│ │ │ └── NotesRecyclerAdapter.java
│ │ │ ├── async
│ │ │ ├── DeleteAsyncTask.java
│ │ │ ├── InsertAsyncTask.java
│ │ │ └── UpdateAsyncTask.java
│ │ │ ├── models
│ │ │ └── Note.java
│ │ │ ├── persistence
│ │ │ ├── NoteDao.java
│ │ │ ├── NoteDatabase.java
│ │ │ └── NoteRepository.java
│ │ │ └── util
│ │ │ ├── Utility.java
│ │ │ └── VerticalSpacingItemDecorator.java
│ └── res
│ │ ├── drawable-v24
│ │ ├── ic_add_black_24dp.xml
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── ic_arrow_back_black_24dp.xml
│ │ ├── ic_check_black_24dp.xml
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_note.xml
│ │ ├── activity_notes_list.xml
│ │ ├── layout_note_list_item.xml
│ │ └── layout_note_toolbar.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── codingwithmitch
│ └── notes
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/libraries
5 | /.idea/modules.xml
6 | /.idea/workspace.xml
7 | .DS_Store
8 | /build
9 | /captures
10 | .externalNativeBuild
11 |
--------------------------------------------------------------------------------
/.idea/caches/build_file_checksums.ser:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/.idea/caches/build_file_checksums.ser
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | In this course I teach you the best practice way to interact with an SQLite database locally on the android device. The room persistence library was designed to simplify interactions with SQLite on the device.
7 |
8 | This course is ideal for beginners. If you have absolutely zero experience programming on android, or even programming in general, this is the course for you.
9 |
10 | Here's what you will see in the course:
11 |
12 | Every line of code is written and explained on video
13 | Installing Android Studio
14 | How to plan the development of your apps
15 | Introduction to Android Studio
16 | Creating your first app
17 | Debugging tips and tricks and the android logcat
18 | Themes, color schemes, hex colors and styles
19 | Building Custom Toolbars
20 | Customizing Toolbar Behaviors with CoordinatorLayout and AppBarLayout
21 | Implementing a RecyclerView
22 | RecyclerView OnClickListeners
23 | Navigating to a new activity with RecyclerView Click
24 | Navigating to different activities using intents
25 | Passing data between activities using a bundle
26 | Passing data between activities using intent extras
27 | Threading and AsyncTask basics
28 | Custom layouts oriented around custom data models
29 | Building custom data models
30 | Using proper architecture patterns with Room
31 | Read, Write, Update and Delete SQLite database transactions
32 | And much more...
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | applicationId "com.codingwithmitch.notes"
7 | minSdkVersion 23
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(dir: 'libs', include: ['*.jar'])
23 | implementation 'com.android.support:appcompat-v7:28.0.0'
24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
25 | testImplementation 'junit:junit:4.12'
26 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
28 |
29 | def room_version = "1.1.1"
30 | implementation "android.arch.persistence.room:runtime:$room_version"
31 | annotationProcessor "android.arch.persistence.room:compiler:$room_version"
32 |
33 | //RecyclerView
34 | implementation 'com.android.support:recyclerview-v7:28.0.0'
35 |
36 | //Support Design (toolbars)
37 | implementation 'com.android.support:design:28.0.0'
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/codingwithmitch/notes/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.codingwithmitch.notes", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/LinedEditText.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 |
10 | public class LinedEditText extends android.support.v7.widget.AppCompatEditText {
11 |
12 | private static final String TAG = "LinedEditText";
13 |
14 | private Rect mRect;
15 | private Paint mPaint;
16 |
17 |
18 | // we need this constructor for LayoutInflater
19 | public LinedEditText(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 |
22 | mRect = new Rect();
23 | mPaint = new Paint();
24 | mPaint.setStyle(Paint.Style.STROKE);
25 | mPaint.setStrokeWidth(2);
26 | mPaint.setColor(0xFFFFD966); // Color of the lines on paper
27 |
28 | }
29 |
30 | @Override
31 | protected void onDraw(Canvas canvas) {
32 |
33 | // get the height of the view
34 | int height = ((View)this.getParent()).getHeight();
35 |
36 | int lineHeight = getLineHeight();
37 | int numberOfLines = height / lineHeight;
38 |
39 | Rect r = mRect;
40 | Paint paint = mPaint;
41 |
42 | int baseline = getLineBounds(0, r);
43 |
44 | for (int i = 0; i < numberOfLines; i++) {
45 |
46 | canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
47 |
48 | baseline += lineHeight;
49 | }
50 |
51 | super.onDraw(canvas);
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/NoteActivity.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.text.Editable;
6 | import android.text.TextWatcher;
7 | import android.util.Log;
8 | import android.view.GestureDetector;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.widget.EditText;
12 | import android.widget.ImageButton;
13 | import android.widget.RelativeLayout;
14 | import android.widget.TextView;
15 |
16 | import com.codingwithmitch.notes.models.Note;
17 | import com.codingwithmitch.notes.persistence.NoteRepository;
18 | import com.codingwithmitch.notes.util.Utility;
19 |
20 | public class NoteActivity extends AppCompatActivity implements
21 | View.OnTouchListener,
22 | GestureDetector.OnGestureListener,
23 | GestureDetector.OnDoubleTapListener,
24 | View.OnClickListener,
25 | TextWatcher
26 | {
27 |
28 | private static final String TAG = "NoteActivity";
29 | private static final int EDIT_MODE_ENABLED = 1;
30 | private static final int EDIT_MODE_DISABLED = 0;
31 |
32 | // UI components
33 | private LinedEditText mLinedEditText;
34 | private EditText mEditTitle;
35 | private TextView mViewTitle;
36 | private RelativeLayout mCheckContainer, mBackArrowContainer;
37 | private ImageButton mCheck, mBackArrow;
38 |
39 |
40 | // vars
41 | private boolean mIsNewNote;
42 | private Note mNoteInitial;
43 | private GestureDetector mGestureDetector;
44 | private int mMode;
45 | private NoteRepository mNoteRepository;
46 | private Note mNoteFinal;
47 |
48 |
49 | @Override
50 | protected void onCreate(Bundle savedInstanceState) {
51 | super.onCreate(savedInstanceState);
52 | setContentView(R.layout.activity_note);
53 | mLinedEditText = findViewById(R.id.note_text);
54 | mEditTitle = findViewById(R.id.note_edit_title);
55 | mViewTitle = findViewById(R.id.note_text_title);
56 | mCheck = findViewById(R.id.toolbar_check);
57 | mBackArrow = findViewById(R.id.toolbar_back_arrow);
58 | mCheckContainer = findViewById(R.id.check_container);
59 | mBackArrowContainer = findViewById(R.id.back_arrow_container);
60 |
61 | mNoteRepository = new NoteRepository(this);
62 |
63 | setListeners();
64 |
65 | if(getIncomingIntent()){
66 | setNewNoteProperties();
67 | enableEditMode();
68 | }
69 | else{
70 | setNoteProperties();
71 | disableContentInteraction();
72 | }
73 | }
74 |
75 | private void saveChanges(){
76 | if(mIsNewNote){
77 | saveNewNote();
78 | }else{
79 | updateNote();
80 | }
81 | }
82 |
83 | public void updateNote() {
84 | mNoteRepository.updateNoteTask(mNoteFinal);
85 | }
86 |
87 | public void saveNewNote() {
88 | mNoteRepository.insertNoteTask(mNoteFinal);
89 | }
90 |
91 | private void setListeners(){
92 | mGestureDetector = new GestureDetector(this, this);
93 | mLinedEditText.setOnTouchListener(this);
94 | mCheck.setOnClickListener(this);
95 | mViewTitle.setOnClickListener(this);
96 | mBackArrow.setOnClickListener(this);
97 | mEditTitle.addTextChangedListener(this);
98 | }
99 |
100 | private boolean getIncomingIntent(){
101 | if(getIntent().hasExtra("selected_note")){
102 | mNoteInitial = getIntent().getParcelableExtra("selected_note");
103 |
104 | mNoteFinal = new Note();
105 | mNoteFinal.setTitle(mNoteInitial.getTitle());
106 | mNoteFinal.setContent(mNoteInitial.getContent());
107 | mNoteFinal.setTimestamp(mNoteInitial.getTimestamp());
108 | mNoteFinal.setId(mNoteInitial.getId());
109 |
110 | mMode = EDIT_MODE_ENABLED;
111 | mIsNewNote = false;
112 | return false;
113 | }
114 | mMode = EDIT_MODE_ENABLED;
115 | mIsNewNote = true;
116 | return true;
117 | }
118 |
119 | private void disableContentInteraction(){
120 | mLinedEditText.setKeyListener(null);
121 | mLinedEditText.setFocusable(false);
122 | mLinedEditText.setFocusableInTouchMode(false);
123 | mLinedEditText.setCursorVisible(false);
124 | mLinedEditText.clearFocus();
125 | }
126 |
127 | private void enableContentInteraction(){
128 | mLinedEditText.setKeyListener(new EditText(this).getKeyListener());
129 | mLinedEditText.setFocusable(true);
130 | mLinedEditText.setFocusableInTouchMode(true);
131 | mLinedEditText.setCursorVisible(true);
132 | mLinedEditText.requestFocus();
133 | }
134 |
135 | private void enableEditMode(){
136 | mBackArrowContainer.setVisibility(View.GONE);
137 | mCheckContainer.setVisibility(View.VISIBLE);
138 |
139 | mViewTitle.setVisibility(View.GONE);
140 | mEditTitle.setVisibility(View.VISIBLE);
141 |
142 | mMode = EDIT_MODE_ENABLED;
143 |
144 | enableContentInteraction();
145 | }
146 |
147 | private void disableEditMode(){
148 | Log.d(TAG, "disableEditMode: called.");
149 | mBackArrowContainer.setVisibility(View.VISIBLE);
150 | mCheckContainer.setVisibility(View.GONE);
151 |
152 | mViewTitle.setVisibility(View.VISIBLE);
153 | mEditTitle.setVisibility(View.GONE);
154 |
155 | mMode = EDIT_MODE_DISABLED;
156 |
157 | disableContentInteraction();
158 |
159 | // Check if they typed anything into the note. Don't want to save an empty note.
160 | String temp = mLinedEditText.getText().toString();
161 | temp = temp.replace("\n", "");
162 | temp = temp.replace(" ", "");
163 | if(temp.length() > 0){
164 | mNoteFinal.setTitle(mEditTitle.getText().toString());
165 | mNoteFinal.setContent(mLinedEditText.getText().toString());
166 | String timestamp = Utility.getCurrentTimeStamp();
167 | mNoteFinal.setTimestamp(timestamp);
168 |
169 | Log.d(TAG, "disableEditMode: initial: " + mNoteInitial.toString());
170 | Log.d(TAG, "disableEditMode: final: " + mNoteFinal.toString());
171 |
172 | // If the note was altered, save it.
173 | if(!mNoteFinal.getContent().equals(mNoteInitial.getContent())
174 | || !mNoteFinal.getTitle().equals(mNoteInitial.getTitle())){
175 | Log.d(TAG, "disableEditMode: called?");
176 | saveChanges();
177 | }
178 | }
179 | }
180 |
181 | private void setNewNoteProperties(){
182 | mViewTitle.setText("Note Title");
183 | mEditTitle.setText("Note Title");
184 |
185 | mNoteFinal = new Note();
186 | mNoteInitial = new Note();
187 | mNoteInitial.setTitle("Note Title");
188 | }
189 |
190 | private void setNoteProperties(){
191 | mViewTitle.setText(mNoteInitial.getTitle());
192 | mEditTitle.setText(mNoteInitial.getTitle());
193 | mLinedEditText.setText(mNoteInitial.getContent());
194 | }
195 |
196 | @Override
197 | public boolean onTouch(View view, MotionEvent motionEvent) {
198 | return mGestureDetector.onTouchEvent(motionEvent);
199 | }
200 |
201 | @Override
202 | public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
203 | return false;
204 | }
205 |
206 | @Override
207 | public boolean onDoubleTap(MotionEvent motionEvent) {
208 | Log.d(TAG, "onDoubleTap: double tapped.");
209 | enableEditMode();
210 | return false;
211 | }
212 |
213 | @Override
214 | public boolean onDoubleTapEvent(MotionEvent motionEvent) {
215 | return false;
216 | }
217 |
218 | @Override
219 | public boolean onDown(MotionEvent motionEvent) {
220 | return false;
221 | }
222 |
223 | @Override
224 | public void onShowPress(MotionEvent motionEvent) {
225 |
226 | }
227 |
228 | @Override
229 | public boolean onSingleTapUp(MotionEvent motionEvent) {
230 | return false;
231 | }
232 |
233 | @Override
234 | public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
235 | return false;
236 | }
237 |
238 | @Override
239 | public void onLongPress(MotionEvent motionEvent) {
240 |
241 | }
242 |
243 | @Override
244 | public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
245 | return false;
246 | }
247 |
248 | @Override
249 | public void onClick(View view) {
250 | switch (view.getId()){
251 | case R.id.toolbar_back_arrow:{
252 | finish();
253 | break;
254 | }
255 | case R.id.toolbar_check:{
256 | disableEditMode();
257 | break;
258 | }
259 | case R.id.note_text_title:{
260 | enableEditMode();
261 | mEditTitle.requestFocus();
262 | mEditTitle.setSelection(mEditTitle.length());
263 | break;
264 | }
265 | }
266 | }
267 |
268 | @Override
269 | public void onBackPressed() {
270 | if(mMode == EDIT_MODE_ENABLED){
271 | onClick(mCheck);
272 | }
273 | else{
274 | super.onBackPressed();
275 | }
276 | }
277 |
278 | @Override
279 | protected void onSaveInstanceState(Bundle outState) {
280 | super.onSaveInstanceState(outState);
281 | outState.putInt("mode", mMode);
282 | }
283 |
284 | @Override
285 | protected void onRestoreInstanceState(Bundle savedInstanceState) {
286 | super.onRestoreInstanceState(savedInstanceState);
287 | mMode = savedInstanceState.getInt("mode");
288 | if(mMode == EDIT_MODE_ENABLED){
289 | enableEditMode();
290 | }
291 | }
292 |
293 | @Override
294 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
295 |
296 | }
297 |
298 | @Override
299 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
300 | mViewTitle.setText(charSequence.toString());
301 | }
302 |
303 | @Override
304 | public void afterTextChanged(Editable editable) {
305 |
306 | }
307 | }
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/NotesListActivity.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes;
2 |
3 | import android.arch.lifecycle.Observer;
4 | import android.content.Intent;
5 | import android.support.annotation.Nullable;
6 | import android.support.design.widget.FloatingActionButton;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.os.Bundle;
9 | import android.support.v7.widget.LinearLayoutManager;
10 | import android.support.v7.widget.RecyclerView;
11 | import android.support.v7.widget.Toolbar;
12 | import android.support.v7.widget.helper.ItemTouchHelper;
13 | import android.util.Log;
14 | import android.view.View;
15 |
16 | import com.codingwithmitch.notes.adapters.NotesRecyclerAdapter;
17 | import com.codingwithmitch.notes.models.Note;
18 | import com.codingwithmitch.notes.persistence.NoteRepository;
19 | import com.codingwithmitch.notes.util.VerticalSpacingItemDecorator;
20 |
21 | import java.util.ArrayList;
22 | import java.util.List;
23 |
24 | public class NotesListActivity extends AppCompatActivity implements
25 | NotesRecyclerAdapter.OnNoteListener,
26 | FloatingActionButton.OnClickListener
27 | {
28 |
29 | private static final String TAG = "NotesListActivity";
30 |
31 | // ui components
32 | private RecyclerView mRecyclerView;
33 |
34 | // vars
35 | private ArrayList mNotes = new ArrayList<>();
36 | private NotesRecyclerAdapter mNoteRecyclerAdapter;
37 | private NoteRepository mNoteRepository;
38 |
39 |
40 | @Override
41 | protected void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | setContentView(R.layout.activity_notes_list);
44 | mRecyclerView = findViewById(R.id.recyclerView);
45 |
46 | findViewById(R.id.fab).setOnClickListener(this);
47 |
48 | initRecyclerView();
49 | mNoteRepository = new NoteRepository(this);
50 | retrieveNotes();
51 | // insertFakeNotes();
52 |
53 | setSupportActionBar((Toolbar)findViewById(R.id.notes_toolbar));
54 | setTitle("Notes");
55 | }
56 |
57 |
58 | private void retrieveNotes() {
59 | mNoteRepository.retrieveNotesTask().observe(this, new Observer>() {
60 | @Override
61 | public void onChanged(@Nullable List notes) {
62 | if(mNotes.size() > 0){
63 | mNotes.clear();
64 | }
65 | if(notes != null){
66 | mNotes.addAll(notes);
67 | }
68 | mNoteRecyclerAdapter.notifyDataSetChanged();
69 | }
70 | });
71 | }
72 |
73 | private void insertFakeNotes(){
74 | for(int i = 0; i < 1000; i++){
75 | Note note = new Note();
76 | note.setTitle("title #" + i);
77 | note.setContent("content #: " + i);
78 | note.setTimestamp("Jan 2019");
79 | mNotes.add(note);
80 | }
81 | mNoteRecyclerAdapter.notifyDataSetChanged();
82 | }
83 |
84 | private void initRecyclerView(){
85 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
86 | mRecyclerView.setLayoutManager(linearLayoutManager);
87 | VerticalSpacingItemDecorator itemDecorator = new VerticalSpacingItemDecorator(10);
88 | mRecyclerView.addItemDecoration(itemDecorator);
89 | new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(mRecyclerView);
90 | mNoteRecyclerAdapter = new NotesRecyclerAdapter(mNotes, this);
91 | mRecyclerView.setAdapter(mNoteRecyclerAdapter);
92 | }
93 |
94 |
95 | @Override
96 | public void onNoteClick(int position) {
97 | Intent intent = new Intent(this, NoteActivity.class);
98 | intent.putExtra("selected_note", mNotes.get(position));
99 | startActivity(intent);
100 | }
101 |
102 | @Override
103 | public void onClick(View view) {
104 | Intent intent = new Intent(this, NoteActivity.class);
105 | startActivity(intent);
106 | }
107 |
108 | private void deleteNote(Note note) {
109 | mNotes.remove(note);
110 | mNoteRecyclerAdapter.notifyDataSetChanged();
111 |
112 | mNoteRepository.deleteNoteTask(note);
113 | }
114 |
115 | ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
116 | @Override
117 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
118 | return false;
119 | }
120 |
121 | @Override
122 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
123 | deleteNote(mNotes.get(viewHolder.getAdapterPosition()));
124 | }
125 | };
126 | }
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/adapters/NotesRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.adapters;
2 |
3 |
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.util.Log;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import com.codingwithmitch.notes.R;
13 | import com.codingwithmitch.notes.models.Note;
14 | import com.codingwithmitch.notes.util.Utility;
15 |
16 |
17 | import java.util.ArrayList;
18 |
19 | public class NotesRecyclerAdapter extends RecyclerView.Adapter {
20 |
21 | private static final String TAG = "NotesRecyclerAdapter";
22 |
23 | private ArrayList mNotes = new ArrayList<>();
24 | private OnNoteListener mOnNoteListener;
25 |
26 | public NotesRecyclerAdapter(ArrayList mNotes, OnNoteListener onNoteListener) {
27 | this.mNotes = mNotes;
28 | this.mOnNoteListener = onNoteListener;
29 | }
30 |
31 | @NonNull
32 | @Override
33 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
34 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_note_list_item, parent, false);
35 | return new ViewHolder(view, mOnNoteListener);
36 | }
37 |
38 | @Override
39 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
40 |
41 | try{
42 | String month = mNotes.get(position).getTimestamp().substring(0, 2);
43 | month = Utility.getMonthFromNumber(month);
44 | String year = mNotes.get(position).getTimestamp().substring(3);
45 | String timestamp = month + " " + year;
46 | holder.timestamp.setText(timestamp);
47 | holder.title.setText(mNotes.get(position).getTitle());
48 | }catch (NullPointerException e){
49 | Log.e(TAG, "onBindViewHolder: Null Pointer: " + e.getMessage() );
50 | }
51 | }
52 |
53 | @Override
54 | public int getItemCount() {
55 | return mNotes.size();
56 | }
57 |
58 | public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
59 |
60 | TextView timestamp, title;
61 | OnNoteListener mOnNoteListener;
62 |
63 | public ViewHolder(View itemView, OnNoteListener onNoteListener) {
64 | super(itemView);
65 | timestamp = itemView.findViewById(R.id.note_timestamp);
66 | title = itemView.findViewById(R.id.note_title);
67 | mOnNoteListener = onNoteListener;
68 |
69 | itemView.setOnClickListener(this);
70 | }
71 |
72 | @Override
73 | public void onClick(View view) {
74 | Log.d(TAG, "onClick: " + getAdapterPosition());
75 | mOnNoteListener.onNoteClick(getAdapterPosition());
76 | }
77 | }
78 |
79 | public interface OnNoteListener{
80 | void onNoteClick(int position);
81 | }
82 | }
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/async/DeleteAsyncTask.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.async;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import com.codingwithmitch.notes.models.Note;
6 | import com.codingwithmitch.notes.persistence.NoteDao;
7 |
8 | public class DeleteAsyncTask extends AsyncTask {
9 |
10 | private NoteDao mNoteDao;
11 |
12 | public DeleteAsyncTask(NoteDao dao) {
13 | mNoteDao = dao;
14 | }
15 |
16 | @Override
17 | protected Void doInBackground(Note... notes) {
18 | mNoteDao.delete(notes);
19 | return null;
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/async/InsertAsyncTask.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.async;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import com.codingwithmitch.notes.models.Note;
6 | import com.codingwithmitch.notes.persistence.NoteDao;
7 |
8 | public class InsertAsyncTask extends AsyncTask {
9 |
10 | private NoteDao mNoteDao;
11 |
12 | public InsertAsyncTask(NoteDao dao) {
13 | mNoteDao = dao;
14 | }
15 |
16 | @Override
17 | protected Void doInBackground(Note... notes) {
18 | mNoteDao.insertNotes(notes);
19 | return null;
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/async/UpdateAsyncTask.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.async;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import com.codingwithmitch.notes.models.Note;
6 | import com.codingwithmitch.notes.persistence.NoteDao;
7 |
8 | public class UpdateAsyncTask extends AsyncTask {
9 |
10 | private NoteDao mNoteDao;
11 |
12 | public UpdateAsyncTask(NoteDao dao) {
13 | mNoteDao = dao;
14 | }
15 |
16 | @Override
17 | protected Void doInBackground(Note... notes) {
18 | mNoteDao.updateNotes(notes);
19 | return null;
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/models/Note.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.models;
2 |
3 | import android.arch.persistence.room.ColumnInfo;
4 | import android.arch.persistence.room.Entity;
5 | import android.arch.persistence.room.Ignore;
6 | import android.arch.persistence.room.PrimaryKey;
7 | import android.os.Parcel;
8 | import android.os.Parcelable;
9 |
10 | @Entity(tableName = "notes")
11 | public class Note implements Parcelable {
12 |
13 | @PrimaryKey(autoGenerate = true)
14 | private int id;
15 |
16 | @ColumnInfo(name = "title")
17 | private String title;
18 |
19 | @ColumnInfo(name = "content")
20 | private String content;
21 |
22 | @ColumnInfo(name = "timestamp")
23 | private String timestamp;
24 |
25 | public Note(String title, String content, String timestamp) {
26 | this.title = title;
27 | this.content = content;
28 | this.timestamp = timestamp;
29 | }
30 |
31 | @Ignore
32 | public Note() {
33 |
34 | }
35 |
36 |
37 | protected Note(Parcel in) {
38 | id = in.readInt();
39 | title = in.readString();
40 | content = in.readString();
41 | timestamp = in.readString();
42 | }
43 |
44 | public static final Creator CREATOR = new Creator() {
45 | @Override
46 | public Note createFromParcel(Parcel in) {
47 | return new Note(in);
48 | }
49 |
50 | @Override
51 | public Note[] newArray(int size) {
52 | return new Note[size];
53 | }
54 | };
55 |
56 | public int getId() {
57 | return id;
58 | }
59 |
60 | public void setId(int id) {
61 | this.id = id;
62 | }
63 |
64 | public String getTitle() {
65 | return title;
66 | }
67 |
68 | public void setTitle(String title) {
69 | this.title = title;
70 | }
71 |
72 | public String getContent() {
73 | return content;
74 | }
75 |
76 | public void setContent(String content) {
77 | this.content = content;
78 | }
79 |
80 | public String getTimestamp() {
81 | return timestamp;
82 | }
83 |
84 | public void setTimestamp(String timestamp) {
85 | this.timestamp = timestamp;
86 | }
87 |
88 | @Override
89 | public String toString() {
90 | return "Note{" +
91 | "title='" + title + '\'' +
92 | ", content='" + content + '\'' +
93 | ", timestamp='" + timestamp + '\'' +
94 | '}';
95 | }
96 |
97 |
98 | @Override
99 | public int describeContents() {
100 | return 0;
101 | }
102 |
103 | @Override
104 | public void writeToParcel(Parcel parcel, int i) {
105 | parcel.writeInt(id);
106 | parcel.writeString(title);
107 | parcel.writeString(content);
108 | parcel.writeString(timestamp);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/persistence/NoteDao.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.persistence;
2 |
3 | import android.arch.lifecycle.LiveData;
4 | import android.arch.persistence.room.Dao;
5 | import android.arch.persistence.room.Delete;
6 | import android.arch.persistence.room.Insert;
7 | import android.arch.persistence.room.Query;
8 | import android.arch.persistence.room.Update;
9 |
10 | import com.codingwithmitch.notes.models.Note;
11 |
12 | import java.util.List;
13 |
14 | @Dao
15 | public interface NoteDao {
16 |
17 | @Insert
18 | long[] insertNotes(Note... notes);
19 |
20 | @Query("SELECT * FROM notes")
21 | LiveData> getNotes();
22 |
23 | @Delete
24 | int delete(Note... notes);
25 |
26 | @Update
27 | int updateNotes(Note... notes);
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/persistence/NoteDatabase.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.persistence;
2 |
3 | import android.arch.persistence.room.Database;
4 | import android.arch.persistence.room.Room;
5 | import android.arch.persistence.room.RoomDatabase;
6 | import android.content.Context;
7 |
8 | import com.codingwithmitch.notes.models.Note;
9 |
10 | @Database(entities = {Note.class}, version = 1)
11 | public abstract class NoteDatabase extends RoomDatabase {
12 |
13 | public static final String DATABASE_NAME = "notes_db";
14 |
15 | private static NoteDatabase instance;
16 |
17 | static NoteDatabase getInstance(final Context context){
18 | if(instance == null){
19 | instance = Room.databaseBuilder(
20 | context.getApplicationContext(),
21 | NoteDatabase.class,
22 | DATABASE_NAME
23 | ).build();
24 | }
25 | return instance;
26 | }
27 |
28 | public abstract NoteDao getNoteDao();
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/persistence/NoteRepository.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.persistence;
2 |
3 |
4 | import android.arch.lifecycle.LiveData;
5 | import android.content.Context;
6 |
7 | import com.codingwithmitch.notes.async.DeleteAsyncTask;
8 | import com.codingwithmitch.notes.async.InsertAsyncTask;
9 | import com.codingwithmitch.notes.async.UpdateAsyncTask;
10 | import com.codingwithmitch.notes.models.Note;
11 |
12 | import java.util.List;
13 |
14 | public class NoteRepository {
15 |
16 | private NoteDatabase mNoteDatabase;
17 |
18 | public NoteRepository(Context context) {
19 | mNoteDatabase = NoteDatabase.getInstance(context);
20 | }
21 |
22 | public void insertNoteTask(Note note){
23 | new InsertAsyncTask(mNoteDatabase.getNoteDao()).execute(note);
24 | }
25 |
26 | public void updateNoteTask(Note note){
27 | new UpdateAsyncTask(mNoteDatabase.getNoteDao()).execute(note);
28 | }
29 |
30 | public LiveData> retrieveNotesTask() {
31 | return mNoteDatabase.getNoteDao().getNotes();
32 | }
33 |
34 | public void deleteNoteTask(Note note){
35 | new DeleteAsyncTask(mNoteDatabase.getNoteDao()).execute(note);
36 | }
37 | }
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/util/Utility.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.util;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 |
6 | public class Utility {
7 |
8 | private static final String TAG = "Utility";
9 |
10 | public static String getCurrentTimeStamp(){
11 | try {
12 |
13 | SimpleDateFormat dateFormat = new SimpleDateFormat("MM-yyyy"); //MUST USE LOWERCASE 'y'. API 23- can't use uppercase
14 | String currentDateTime = dateFormat.format(new Date()); // Find todays date
15 |
16 | return currentDateTime;
17 | } catch (Exception e) {
18 | e.printStackTrace();
19 |
20 | return null;
21 | }
22 | }
23 |
24 | public static String getMonthFromNumber(String monthNumber){
25 | switch(monthNumber){
26 | case "01":{
27 | return "Jan";
28 | }
29 | case "02":{
30 | return "Feb";
31 | }
32 | case "03":{
33 | return "Mar";
34 | }
35 | case "04":{
36 | return "Apr";
37 | }
38 | case "05":{
39 | return "May";
40 | }
41 | case "06":{
42 | return "Jun";
43 | }
44 | case "07":{
45 | return "Jul";
46 | }
47 | case "08":{
48 | return "Aug";
49 | }
50 | case "09":{
51 | return "Sep";
52 | }
53 | case "10":{
54 | return "Oct";
55 | }
56 | case "11":{
57 | return "Nov";
58 | }
59 | case "12":{
60 | return "Dec";
61 | }
62 |
63 | default:{
64 | return "Error";
65 | }
66 | }
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/codingwithmitch/notes/util/VerticalSpacingItemDecorator.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes.util;
2 |
3 | import android.graphics.Rect;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.View;
6 |
7 | public class VerticalSpacingItemDecorator extends RecyclerView.ItemDecoration{
8 |
9 | private final int verticalSpaceHeight;
10 |
11 | public VerticalSpacingItemDecorator(int verticalSpaceHeight) {
12 | this.verticalSpaceHeight = verticalSpaceHeight;
13 | }
14 |
15 | @Override
16 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
17 | RecyclerView.State state) {
18 |
19 | outRect.bottom = verticalSpaceHeight;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_add_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_back_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_note.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_notes_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_note_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
27 |
28 |
32 |
33 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_note_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
24 |
25 |
26 |
27 |
28 |
34 |
35 |
42 |
43 |
44 |
45 |
55 |
56 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffd24d
4 | #e6ac00
5 | #d9d9d9
6 |
7 | #ffffb3
8 | #ffdf80
9 | #ffd24d
10 | #d9d9d9
11 | #a2a2a2
12 | #000
13 | #fff
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Notes
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/test/java/com/codingwithmitch/notes/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.codingwithmitch.notes;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.1.3'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchtabian/SQLite-for-Beginners-2019/37e37de210a6b801bd0d33931c5a9dc4d1a4c462/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 03 08:04:05 PDT 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------