Skip to content

Instantly share code, notes, and snippets.

@haerulmuttaqin
Created December 25, 2018 18:50
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
  • Save haerulmuttaqin/762b4f041cf562ba6fd72cac1c1221cc to your computer and use it in GitHub Desktop.
Save haerulmuttaqin/762b4f041cf562ba6fd72cac1c1221cc to your computer and use it in GitHub Desktop.
Android CRUD Tutorial | • RETROFIT • PHP • MYSQL (https://youtu.be/Vh92eSAEu5c)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".activity.editor.EditorActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="20dp">
<EditText
android:id="@+id/title"
android:hint="@string/to_do"
android:textSize="25sp"
android:inputType="textCapSentences"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="Autofill" />
<EditText
android:id="@+id/note"
android:layout_below="@id/title"
android:hint="@string/enter_note"
android:inputType="textMultiLine"
android:minLines="6"
android:gravity="top|start"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="Autofill" />
<com.thebluealliance.spectrum.SpectrumPalette
android:id="@+id/palette"
android:layout_below="@id/note"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:spectrum_colors="@array/demo_colors"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.main.MainActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/add"
android:layout_margin="16dp"
android:layout_gravity="bottom|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add"/>
</android.support.design.widget.CoordinatorLayout>
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static final String BASE_URL = "http://your-domain-name.000webhostapp.com/";
private static Retrofit retrofit;
public static Retrofit getApiClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
import com.haerulmuttaqin.mynotesapp.model.Note;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
public interface ApiInterface {
@FormUrlEncoded
@POST("save.php")
Call<Note> saveNote(
@Field("title") String title,
@Field("note") String note,
@Field("color") int color
);
@GET("notes.php")
Call<List<Note>> getNotes();
@FormUrlEncoded
@POST("update.php")
Call<Note> updateNote(
@Field("id") int id,
@Field("title") String title,
@Field("note") String note,
@Field("color") int color
);
@FormUrlEncoded
@POST("delete.php")
Call<Note> deleteNote( @Field("id") int id );
}
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.thebluealliance:spectrum:0.7.1'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#1d1f2d</color>
<color name="colorPrimaryDark">#15161e</color>
<color name="colorAccent">#189be7</color>
<!--color palete-->
<color name="white">#dde6ec</color>
<color name="blue">#7ec4ed</color>
<color name="yellow">#d0fc7d</color>
<color name="pink">#ed579a</color>
<color name="green">#2aed76</color>
<array name="demo_colors">
<item>@color/white</item>
<item>@color/blue</item>
<item>@color/yellow</item>
<item>@color/pink</item>
<item>@color/green</item>
</array>
</resources>
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Toast;
import com.haerulmuttaqin.mynotesapp.R;
import com.haerulmuttaqin.mynotesapp.api.ApiClient;
import com.haerulmuttaqin.mynotesapp.api.ApiInterface;
import com.haerulmuttaqin.mynotesapp.model.Note;
import com.thebluealliance.spectrum.SpectrumPalette;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class EditorActivity extends AppCompatActivity implements EditorView {
EditText et_title, et_note;
ProgressDialog progressDialog;
SpectrumPalette palette;
EditorPresenter presenter;
int color, id;
String title, note;
Menu actionMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editor);
et_title = findViewById(R.id.title);
et_note = findViewById(R.id.note);
palette = findViewById(R.id.palette);
palette.setOnColorSelectedListener(
clr -> color = clr
);
// Progress Dialog
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please wait...");
presenter = new EditorPresenter(this);
Intent intent = getIntent();
id = intent.getIntExtra("id", 0);
title = intent.getStringExtra("title");
note = intent.getStringExtra("note");
color = intent.getIntExtra("color", 0);
setDataFromIntentExtra();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_editor, menu);
actionMenu = menu;
if (id != 0) {
actionMenu.findItem(R.id.edit).setVisible(true);
actionMenu.findItem(R.id.delete).setVisible(true);
actionMenu.findItem(R.id.save).setVisible(false);
actionMenu.findItem(R.id.update).setVisible(false);
} else {
actionMenu.findItem(R.id.edit).setVisible(false);
actionMenu.findItem(R.id.delete).setVisible(false);
actionMenu.findItem(R.id.save).setVisible(true);
actionMenu.findItem(R.id.update).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
String title = et_title.getText().toString().trim();
String note = et_note.getText().toString().trim();
int color = this.color;
switch (item.getItemId()) {
case R.id.save:
//Save
if (title.isEmpty()) {
et_title.setError("Please enter a title");
} else if (note.isEmpty()) {
et_note.setError("Please enter a note");
} else {
presenter.saveNote(title, note, color);
}
return true;
case R.id.edit:
editMode();
actionMenu.findItem(R.id.edit).setVisible(false);
actionMenu.findItem(R.id.delete).setVisible(false);
actionMenu.findItem(R.id.save).setVisible(false);
actionMenu.findItem(R.id.update).setVisible(true);
return true;
case R.id.update:
//Update
if (title.isEmpty()) {
et_title.setError("Please enter a title");
} else if (note.isEmpty()) {
et_note.setError("Please enter a note");
} else {
presenter.updateNote(id, title, note, color);
}
return true;
case R.id.delete:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("Confirm !");
alertDialog.setMessage("Are you sure?");
alertDialog.setNegativeButton("Yes", (dialog, which) -> {
dialog.dismiss();
presenter.deleteNote(id);
});
alertDialog.setPositiveButton("Cencel",
(dialog, which) -> dialog.dismiss());
alertDialog.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void showProgress() {
progressDialog.show();
}
@Override
public void hideProgress() {
progressDialog.hide();
}
@Override
public void onRequestSuccess(String message) {
Toast.makeText(EditorActivity.this,
message,
Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
finish(); //back to main activity
}
@Override
public void onRequestError(String message) {
Toast.makeText(EditorActivity.this,
message,
Toast.LENGTH_SHORT).show();
}
private void setDataFromIntentExtra() {
if (id != 0) {
et_title.setText(title);
et_note.setText(note);
palette.setSelectedColor(color);
getSupportActionBar().setTitle("Update Note");
readMode();
} else {
palette.setSelectedColor(getResources().getColor(R.color.white));
color = getResources().getColor(R.color.white);
editMode();
}
}
private void editMode() {
et_title.setFocusableInTouchMode(true);
et_note.setFocusableInTouchMode(true);
palette.setEnabled(true);
}
private void readMode() {
et_title.setFocusableInTouchMode(false);
et_note.setFocusableInTouchMode(false);
et_title.setFocusable(false);
et_note.setFocusable(false);
palette.setEnabled(false);
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
app:cardCornerRadius="2dp"
app:cardElevation="1dp"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
android:id="@+id/card_item">
<LinearLayout
android:id="@+id/line"
android:layout_width="10dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#49000000"/>
<RelativeLayout
android:padding="10dp"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
android:text="@string/to_do"
android:textSize="18sp"
android:textColor="@android:color/black"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/note"
android:layout_below="@id/title"
android:text="@string/enter_note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"/>
<TextView
android:id="@+id/date"
android:layout_below="@id/note"
android:text="@string/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="end"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
import android.content.Intent;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import com.haerulmuttaqin.mynotesapp.R;
import com.haerulmuttaqin.mynotesapp.activity.editor.EditorActivity;
import com.haerulmuttaqin.mynotesapp.model.Note;
import java.util.List;
public class MainActivity extends AppCompatActivity implements MainView {
private static final int INTENT_ADD = 100;
private static final int INTENT_EDIT = 200;
FloatingActionButton fab;
RecyclerView recyclerView;
SwipeRefreshLayout swipeRefresh;
MainPresenter presenter;
MainAdapter adapter;
MainAdapter.ItemClickListener itemClickListener;
List<Note> note;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipeRefresh = findViewById(R.id.swipe_refresh);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
fab = findViewById(R.id.add);
fab.setOnClickListener(view ->
startActivityForResult(
new Intent(this, EditorActivity.class),
INTENT_ADD)
);
presenter = new MainPresenter(this);
presenter.getData();
swipeRefresh.setOnRefreshListener(
() -> presenter.getData()
);
itemClickListener = ((view, position) -> {
int id = note.get(position).getId();
String title = note.get(position).getTitle();
String notes = note.get(position).getNote();
int color = note.get(position).getColor();
Intent intent = new Intent(this, EditorActivity.class);
intent.putExtra("id", id);
intent.putExtra("title", title);
intent.putExtra("note", notes);
intent.putExtra("color", color);
startActivityForResult(intent, INTENT_EDIT);
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == INTENT_ADD && resultCode == RESULT_OK) {
presenter.getData(); //reload data
}
else if (requestCode == INTENT_EDIT && resultCode == RESULT_OK) {
presenter.getData(); //reload data
}
}
@Override
public void showLoading() {
swipeRefresh.setRefreshing(true);
}
@Override
public void hideLoading() {
swipeRefresh.setRefreshing(false);
}
@Override
public void onGetResult(List<Note> notes) {
adapter = new MainAdapter(this, notes, itemClickListener);
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
note = notes;
}
@Override
public void onErrorLoading(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/edit"
android:title="@string/edit"
android:icon="@drawable/ic_edit"
app:showAsAction="always" />
<item
android:id="@+id/delete"
android:title="@string/delete"
android:icon="@drawable/ic_delete"
app:showAsAction="always" />
<item
android:id="@+id/update"
android:title="@string/update"
android:icon="@drawable/ic_save"
app:showAsAction="always" />
<item
android:id="@+id/save"
android:title="@string/save"
android:icon="@drawable/ic_save"
app:showAsAction="always" />
</menu>
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Note {
@Expose
@SerializedName("id") private int id;
@Expose
@SerializedName("title") private String title;
@Expose
@SerializedName("note") private String note;
@Expose
@SerializedName("color") private int color;
@Expose
@SerializedName("date") private String date;
@Expose
@SerializedName("success") private Boolean success;
@Expose
@SerializedName("message") private String message;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@haerulmuttaqin
Copy link
Author

haerulmuttaqin commented Dec 25, 2018

Android CRUD Tutorial

-RETROFIT
-PHP
-MYSQL

ANDROID CRUD TUTORIAL

@jkariscodes
Copy link

Thank you for this. Really helpful

@Olgaa-Z
Copy link

Olgaa-Z commented Apr 2, 2019

thankyou

@Jordanadopo
Copy link

Thank You!!!! It's very helpful!

@wish75584
Copy link

i have used your php code.
`<?php
header("Content-type:application/json");

require_once('connect.php');

$query = mysqli_query($conn,"SELECT * FROM `retrofit` ") ;

$response = array();

while($row = mysqli_fetch_assoc($query)){
    
    array_push($response,
    array(
        'userId' =>$row['userId'],
        'id' =>$row['id'],
        'title' =>$row['title'],
        'body' =>$row['body']));
}

echo json_encode($response);

?>`

my php code is not giving me proper json .please help.

[{"userId":"1","id":null,"title":"sunt aut facere repellat provident occaecati excepturi optio reprehenderit","body":"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto"},{"userId":"1","id":null,"title":"qui est esse","body":"est rerum tempore vitae\\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam non debitis possimus qui neque nisi nulla"}]

@wish75584
Copy link

i need urgent help

@somayeh-z
Copy link

Please send php code too. I need it very much.

@gargighorai
Copy link

i got error use json setlelient(true at line number1 column number 1

@haerulmuttaqin
Copy link
Author

i got error use json setlelient(true at line number1 column number 1

Please check your json output from php code

@gargighorai
Copy link

how to do that

@aguzri10
Copy link

Where is MainAdapter bro?

@JittuMistry
Copy link

What is EditorPresenter ????

@Haeyzed
Copy link

Haeyzed commented Feb 22, 2020

Hello pls it is not sorting the note post by descending, when i add it goes down, it does not show at the up(latest post).

@noureddineup
Copy link

you're missing multiple files:
MainPresenter
EditorPresenter
MainView ??

@HusseinMohammedHussein
Copy link

Thank you,
have small error is when get color no data get, but when i delete select color line from note.php data get without error...why?
and how can be get color and set as cardview background?
thanks again!

@InnocentKyalo
Copy link

I keep on getting this error "Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $". Anyone who can help? Thanks in advance.

@mohammedamin19
Copy link

can you send me the php files for this project 
thank you

@SyahrinRamadandi
Copy link

After adding INTENT_ADD, my application force close when I click the add data button Can anyone help?

@technicalyarana
Copy link

I keep on getting this error "Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $". Anyone who can help? Thanks in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment