주) 현재 동작하지 않습니다.

이 글을 읽기 전에 다음 3개의 글을 읽어주세요.
"안드로이드 DB CRUD(쓰기, 읽기, 수정, 삭제) 1 - 프로세스" - http://ilbbang.tistory.com/34
"안드로이드 DB CRUD(쓰기, 읽기, 수정, 삭제) 2 - MariaDB 설정하기" - http://ilbbang.tistory.com/45
"안드로이드 DB CRUD(쓰기, 읽기, 수정, 삭제) 3 - PHP로 MySQL에 접근하기" - http://ilbbang.tistory.com/47
제가 따라해 볼 원문을 다시 확인해 보겠습니다.(출처)
http://freeprojectcode.com/android/android-mysql-basic-crud-operation-tutorial-for-android-studio-project/
(글 게시자가 홈페이지를 초기화 해서 해당 글을 더이상 볼 수 없습니다.)
이제 안드로이드에서 화면 및 구동이 가능하도록 프로그래밍을 해보겠습니다.
화면은 3개를 만들 예정입니다.
1. 쓰기 - 이름, 직책, 급여 입력란에 값을 입력하고 버튼을 클릭하면 DB에 작성 후에 "2. 읽기"으로 이동합니다. 입력하지 않아도 "2. 읽기" 화면으로 이동할 수도 있습니다.
2. 읽기 - 전체 목록을 출력합니다. 특정 목록을 클릭하면 "3.수정 및 삭제" 화면으로 이동합니다. "1. 쓰기" 화면으로 이동할 수도 있습니다.
3. 수정 및 삭제 - "2. 읽기"에서 출력된 목록 중 선택된 항목에 대한 정보를 수정할 수 있는 페이지 입니다. 내용을 변경 후에 버튼을 클릭하면 수정된 내용으로 DB를 update한 후에 "2. 읽기" 화면으로 이동합니다.. 수정하지 않고 "2. 읽기" 화면으로 이동할 수도 있습니다. 삭제 버튼을 클릭하면 선택된 항목을 삭제할 수도 있습니다.
그리고 구동에 필요한 별도의 자바 클래스를 4개 만들 예정입니다.
1. Constant - PHP 파일 주소 목록을 설정합니다.
2. PostRequestHandler - Post 방식의 Requset를 보내기 위한 클래스 입니다. 네트워크 관련 처리기 때문에 별도의 스래드(3. BackgroundWorker)를 생성하여 수행합니다.
3. BackgroundWorker - Background 에서 수행할 매서드가 있는 클래스입니다. Post로 보내기 및 받기 매서드가 있습니다.
4. JsonParser - Json으로 받은 내용을 안드로이드 화면에 출력하기 위해 변환하는 매서드가 있습니다.
안드로이드 스튜디오에서 새로운 프로젝트를
우선 클래스 부터 만들어 보겠습니다. 클래스를 만드는 방법은 아래 그림과 같이 탐색기에서 app 폴더에 마우스를 올린 후에 오른쪽 마우스 버튼을 클릭하고 New - Java Class를 클릭하고 클래스 이름을 입력하고 OK 버튼을 클릭하면 됩니다. 그럼 파일 별 코드를 보겠습니다.

1. Constant.java

public class Constant {      private static final String BASE_PATH = "php파일이있는폴더(마지막에/으로끝냄)";      public static final String CREATE_URL = BASE_PATH + "addEmp.php";     public static final String READ = BASE_PATH + "getAllEmp.php";     public static final String UPDATE = BASE_PATH + "updateEmp.php";     public static final String DELETE = BASE_PATH + "deleteEmp.php";      public static final String GET_METHOD = "GET";     static final String POST_METHOD = "POST"; } 

2. PostRequestHandler.java

import android.os.AsyncTask;  import java.io.UnsupportedEncodingException; import java.util.HashMap;  public class PostRequestHandler extends AsyncTask<Void, Void, String> {     // php URL 주소     String url;     // Key, Value 값     HashMap<String, String> requestedParams;      PostRequestHandler(String url, HashMap<String, String> params){         this.url = url;         this.requestedParams = params;     }      @Override     protected void onPreExecute() {         super.onPreExecute();     }      @Override     protected String doInBackground(Void... voids) {          // post request 보냄         BackgroundWorker backgroundWorker = new BackgroundWorker();         try {             String s = backgroundWorker.postRequestHandler(url, requestedParams);             return s.toString();         } catch (UnsupportedEncodingException e) {             e.printStackTrace();         }          return null;     }      @Override     protected void onPostExecute(String s) {         super.onPostExecute(s);     } } 

3. BackgroundWorker.java

import android.util.Log;  import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map;  public class BackgroundWorker {      // Make a POST Request Handler     public String postRequestHandler(String requestUrl, HashMap<String, String> requestedDataParams) throws UnsupportedEncodingException {          // Set an Empty URL obj in system         URL url;           // Set a String Builder to store result as string         StringBuilder stringBuilder = new StringBuilder();          try {             // Now Initialize URL             url = new URL(requestUrl);              // Make a HTTP url connection             HttpURLConnection connection = (HttpURLConnection) url.openConnection();              // Set Method Type             connection.setRequestMethod(Constant.POST_METHOD);             // Set Connection Time             connection.setConnectTimeout(10000);             connection.setReadTimeout(10000);             // set Input output ok             connection.setDoInput(true);             connection.setDoOutput(true);             // Remove Caches             //connection.setUseCaches(false);             //connection.setDefaultUseCaches(false);               // Creating a url as String with params             StringBuilder url_string = new StringBuilder();              boolean ampersand = false;             for (Map.Entry<String, String> params : requestedDataParams.entrySet() ){                 if (ampersand)                     url_string.append("&");                 else                     ampersand = true;                  url_string.append(URLEncoder.encode(params.getKey(), "UTF-8"));                 url_string.append("=");                 url_string.append(URLEncoder.encode(params.getValue(), "UTF-8"));             }             Log.d("Final Url===", url_string.toString());                //Creating an output stream             OutputStream outputStream = connection.getOutputStream();              // Write Output Steam             BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));             bufferedWriter.write(url_string.toString());              bufferedWriter.flush();             bufferedWriter.close();             outputStream.close();              //        Log.d("Response===", connection.getResponseMessage());              if (connection.getResponseCode() == HttpURLConnection.HTTP_OK){                 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));                  // Local String                 String result;                 while ((result = bufferedReader.readLine()) != null) {                     stringBuilder.append(result);                 }                 //            Log.d("Result===", result);              }         } catch (MalformedURLException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         }          return stringBuilder.toString();     }      // Get Request Handler     public String getRequestHandler(String requestUrl){         // To Store response         StringBuilder stringBuilder = new StringBuilder();          try {             URL url = new URL(requestUrl);             // Open Connection             HttpURLConnection connection = (HttpURLConnection) url.openConnection();             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));              // Local             String result;             while ((result = bufferedReader.readLine()) != null) {                 stringBuilder.append(result + "\n");             }          } catch (MalformedURLException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         }          return null;     }  } 

4. JsonParser.java

import android.util.Log;  import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL;  public class JsonParser {     private static final String TAG = JsonParser.class.getSimpleName();      public String convertJson(String reqUrl) {         String response = null;         try {             URL url = new URL(reqUrl);             HttpURLConnection conn = (HttpURLConnection) url.openConnection();             conn.setRequestMethod("GET");             // read the response             InputStream in = new BufferedInputStream(conn.getInputStream());             response = convertStreamToString(in);         } catch (MalformedURLException e) {             Log.e(TAG, "MalformedURLException: " + e.getMessage());         } catch (ProtocolException e) {             Log.e(TAG, "ProtocolException: " + e.getMessage());         } catch (IOException e) {             Log.e(TAG, "IOException: " + e.getMessage());         } catch (Exception e) {             Log.e(TAG, "Exception: " + e.getMessage());         }         return response;     }      private String convertStreamToString(InputStream is) {         BufferedReader reader = new BufferedReader(new InputStreamReader(is));         StringBuilder sb = new StringBuilder();          String line;         try {             while ((line = reader.readLine()) != null) {                 sb.append(line).append('\n');             }         } catch (IOException e) {             e.printStackTrace();         } finally {             try {                 is.close();             } catch (IOException e) {                 e.printStackTrace();             }         }         return sb.toString();     } } 

이제 위 클래스를 포함한 화면을 만들어 보겠습니다. 추가 화면을를 만드는 방법은 아래 그림과 같이 탐색기에서 app 폴더에 마우스를 올린 후에 오른쪽 마우스 버튼을 클릭하고 New - Java Class를 클릭하고 클래스 이름을 입력하고 OK 버튼을 클릭하면 됩니다. 그럼 파일 별 코드를 보겠습니다.

위 방법으로 "ViewActivity"와 "EditActivity"를 프로젝트에 추가합니다.
이제부터 Activity의 외형 및 코드를 아래와 같이 작성합니다.
화면1. activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:padding="22dp"     tools:context=".MainActivity">      <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:orientation="vertical"         android:padding="11dp">          <TextView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:text="Android PHP MySQL CRUD"             android:textAlignment="center"             android:textColor="#e21ace41"             android:textSize="22dp" />          <TextView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:text="FreeProjectCode.com"             android:textAlignment="center"             android:textColor="#e2f209df"             android:textSize="20dp" />          <EditText             android:id="@+id/name"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="Name" />          <EditText             android:id="@+id/designation"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="Designation" />          <EditText             android:id="@+id/salary"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="Salary" />          <Button             android:id="@+id/btn_add"             android:onClick="createEmployee"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:textColor="#fff"             android:background="#e21ace41"             android:text="Add Employee"/>         <Button             android:id="@+id/btn_list"             android:onClick="employeeList"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:textColor="#fff"             android:layout_marginTop="11dp"             android:background="#e2152099"             android:text="Employee List"/>     </LinearLayout>  </android.support.constraint.ConstraintLayout> 

java코드1. MainActivity.java

import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;  import java.util.HashMap;  public class MainActivity extends AppCompatActivity {      private EditText mName, mDesignation, mSalary;     private Button mBtnAdd;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          // Initialize EditText View         mName = (EditText) findViewById(R.id.name);         mDesignation = (EditText) findViewById(R.id.designation);         mSalary = (EditText) findViewById(R.id.salary);          mBtnAdd = (Button) findViewById(R.id.btn_add);     }      // Create     public void createEmployee(View view){          String name = mName.getText().toString();         String designation = mDesignation.getText().toString();         String salary = mSalary.getText().toString();          HashMap<String, String> requestedParams = new HashMap<>();         requestedParams.put("name", name);         requestedParams.put("designation", designation);         requestedParams.put("salary", salary);         Log.d("HashMap", requestedParams.get("name"));         Toast.makeText(getApplicationContext(), "Success!!! Employee Added Name: " + requestedParams.get("name"), Toast.LENGTH_LONG).show();          PostRequestHandler postRequestHandler = new PostRequestHandler(Constant.CREATE_URL, requestedParams);         postRequestHandler.execute();          employeeList(view);     }      public void employeeList(View view) {         Intent intent = new Intent(MainActivity.this, ViewActivity.class);         startActivity(intent);     }  } 

화면2. activity_view.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ViewActivity">  <RelativeLayout     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="vertical">     <Button         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_marginBottom="11dp"         android:layout_marginTop="11dp"         android:background="#e21bd721"         android:onClick="addEmployee"         android:text="Add New Employee"         android:layout_alignParentBottom="true"         android:textColor="#fff" />      <ListView         android:id="@+id/list"         android:layout_width="match_parent"         android:layout_height="wrap_content" />  </RelativeLayout>  </RelativeLayout > 

여기서 ListView에 단순하게 택스트로 보여줄 수도 있지만 보기 좋은 형식으로 보여주려면 별도의 레이아웃 xml 파일을 만들어 줘야 합니다. 레이아웃을 만드는 방법은 아래 그림과 같이 탐색기에서 app 폴더에 마우스를 올린 후에 오른쪽 마우스 버튼을 클릭하고 New - Android Resource File을 클릭하고 Resource type를 Layout으로 선택한 다음 파일이름, Root element 등을 입력하고 OK 버튼을 클릭하면 됩니다.

위 방법으로 list_item.xml 파일를 프로젝트에 추가합니다.

화면2-1. list_item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="vertical" android:layout_width="match_parent"     android:layout_height="match_parent">      <TextView         android:id="@+id/id"         android:layout_width="0dp"         android:layout_height="0dp"         android:visibility="invisible"/>      <TextView         android:id="@+id/name"         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:paddingBottom="2dip"         android:paddingTop="6dip"         android:textColor="@color/colorPrimaryDark"         android:textSize="16sp"         android:textStyle="bold" />      <TextView         android:id="@+id/designation"         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:paddingBottom="2dip"         android:textColor="@color/colorAccent" />      <TextView         android:id="@+id/salary"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textColor="#5d5d5d"         android:textStyle="bold" />  </LinearLayout> 

java코드2. ViewActivity.java

import android.app.ProgressDialog; import android.content.Intent; import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; import android.widget.Toast;  import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;  import java.util.ArrayList; import java.util.HashMap;  public class ViewActivity extends AppCompatActivity {      private String TAG = MainActivity.class.getSimpleName();      private ProgressDialog pDialog;     private ListView lv;      // URL to get contacts JSON     //private static String url = "http://shapon.website/android/CRUD/getAllEmp.php";      ArrayList<HashMap<String, String>> contactList;      private String id, name, designation, salary;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_view);          contactList = new ArrayList<>();          lv = (ListView) findViewById(R.id.list);          new Handler().execute();          // OnItem Click         lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {             @Override             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {                 //Employee employee = (Employee) adapterView.getItemAtPosition(i);                 Intent intent = new Intent(ViewActivity.this, EditActivity.class);                  id = ((TextView) view.findViewById(R.id.id)).getText().toString();                 name = ((TextView) view.findViewById(R.id.name)).getText().toString();                 designation = ((TextView) view.findViewById(R.id.designation)).getText().toString();                 salary = ((TextView) view.findViewById(R.id.salary)).getText().toString();     //                String id = employee.getId(); //                String name = employee.getName(); //                String designation = employee.getDesignation(); //                String salary = employee.getSalary();                  intent.putExtra("ID", id);                 intent.putExtra("NAME", name);                 intent.putExtra("DESIGNATION", designation);                 intent.putExtra("SALARY", salary);                  startActivity(intent);             }         });     }      public void addEmployee(View view) {         Intent intent = new Intent(ViewActivity.this, MainActivity.class);         startActivity(intent);     }      /**      * Async task class to get json by making HTTP call      */     private class Handler extends AsyncTask<Void, Void, Void> {          private ListAdapter adapter;          @Override         protected void onPreExecute() {             super.onPreExecute();             // Showing progress dialog             pDialog = new ProgressDialog(ViewActivity.this);             pDialog.setMessage("Please wait...");             pDialog.setCancelable(false);             pDialog.show();          }          @Override         protected Void doInBackground(Void... arg0) {             JsonParser sh = new JsonParser();              // Making a request to url and getting response             String jsonStr = sh.convertJson(Constant.READ);              Log.e(TAG, "Response from url: " + jsonStr);              if (jsonStr != null) {                 try {                     JSONObject jsonObj = new JSONObject(jsonStr);                      // Getting JSON Array node                     JSONArray employeeArray = jsonObj.getJSONArray("result");                      // looping through All Contacts                     for (int i = 0; i < employeeArray.length(); i++) {                         JSONObject c = employeeArray.getJSONObject(i);                          String id = c.getString("id");                         String name = c.getString("name");                         String designation = c.getString("designation");                         String salary = c.getString("salary");                          // Phone node is JSON Object //                        JSONObject phone = c.getJSONObject("phone"); //                        String mobile = phone.getString("mobile"); //                        String home = phone.getString("home"); //                        String office = phone.getString("office");                          // tmp hash map for single contact                         HashMap<String, String> employee = new HashMap<>();                          // adding each child node to HashMap key => value                         employee.put("id", id);                         employee.put("name", name);                         employee.put("designation", designation);                         employee.put("salary", salary);                          // adding contact to contact list                         contactList.add(employee);                     }                 } catch (final JSONException e) {                     Log.e(TAG, "Json parsing error: " + e.getMessage());                     runOnUiThread(new Runnable() {                         @Override                         public void run() {                             Toast.makeText(getApplicationContext(),                                     "Json parsing error: " + e.getMessage(),                                     Toast.LENGTH_LONG)                                     .show();                         }                     });                  }             } else {                 Log.e(TAG, "Couldn't get json from server.");                 runOnUiThread(new Runnable() {                     @Override                     public void run() {                         Toast.makeText(getApplicationContext(),                                 "Couldn't get json from server. Check LogCat for possible errors!",                                 Toast.LENGTH_LONG)                                 .show();                     }                 });              }              return null;         }          @Override         protected void onPostExecute(Void result) {             super.onPostExecute(result);             // Dismiss the progress dialog             if (pDialog.isShowing())                 pDialog.dismiss();             /**              * Updating parsed JSON data into ListView              * */             ListAdapter adapter = new SimpleAdapter(                     ViewActivity.this, contactList,                     R.layout.list_item, new String[]{"id", "name", "designation",                     "salary"}, new int[]{R.id.id, R.id.name,                     R.id.designation, R.id.salary});              lv.setAdapter(adapter);           }      }  } 

화면3. activity_edit.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".EditActivity">      <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:orientation="vertical"         android:padding="11dp">          <TextView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:text="Android PHP MySQL CRUD"             android:textAlignment="center"             android:textColor="#e21ace41"             android:textSize="22dp" />          <TextView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:text="FreeProjectCode.com"             android:textAlignment="center"             android:textColor="#e2f209df"             android:textSize="20dp" />           <EditText             android:id="@+id/id"             android:layout_width="0dp"             android:layout_height="0dp"             android:hint="Id"             android:visibility="invisible" />          <EditText             android:id="@+id/name"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="Name" />          <EditText             android:id="@+id/designation"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="Designation" />          <EditText             android:id="@+id/salary"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="Salary" />          <Button             android:id="@+id/btn_update"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:background="#e21ace41"             android:onClick="updateEmployee"             android:text="Edit Employee"             android:textColor="#fff" />          <Button             android:id="@+id/btn_list"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_marginTop="11dp"             android:background="#c28c27a6"             android:onClick="listEmployee"             android:text="Show Employee List"             android:textColor="#fff" />          <Button             android:id="@+id/btn_delete"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_marginTop="11dp"             android:background="#e2d11527"             android:onClick="deleteEmployee"             android:text="Delete Employee"             android:textColor="#fff" />        </LinearLayout>  </android.support.constraint.ConstraintLayout> 

java코드3. EditActivity.java

import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;


import java.util.HashMap; public class EditActivity extends AppCompatActivity { private EditText mId, mName, mDesignation, mSalary; private Button mBtnAdd; //private String mId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit); // Initialize EditText View mId = (EditText) findViewById(R.id.id); mName = (EditText) findViewById(R.id.name); mDesignation = (EditText) findViewById(R.id.designation); mSalary = (EditText) findViewById(R.id.salary); mBtnAdd = (Button) findViewById(R.id.btn_add); Intent intent = getIntent(); Bundle bundle = intent.getExtras(); if (bundle != null){ mId.setText(bundle.getString("ID")); mName.setText(bundle.getString("NAME")); mDesignation.setText(bundle.getString("DESIGNATION")); mSalary.setText(bundle.getString("SALARY")); } } public void updateEmployee(View view) { String id = mId.getText().toString(); String name = mName.getText().toString(); String designation = mDesignation.getText().toString(); String salary = mSalary.getText().toString(); HashMap<String, String> requestedParams = new HashMap<>(); requestedParams.put("id", id); requestedParams.put("name", name); requestedParams.put("designation", designation); requestedParams.put("salary", salary); Log.d("HashMap", requestedParams.get("id")); Toast.makeText(getApplicationContext(), "Success!! Employee Updated ID : " + requestedParams.get("id"), Toast.LENGTH_LONG).show(); PostRequestHandler postRequestHandler = new PostRequestHandler(Constant.UPDATE, requestedParams); postRequestHandler.execute(); listEmployee(view); } public void deleteEmployee(View view) { String id = mId.getText().toString(); // String name = mName.getText().toString(); // String designation = mDesignation.getText().toString(); // String salary = mSalary.getText().toString(); HashMap<String, String> requestedParams = new HashMap<>(); requestedParams.put("id", id); // requestedParams.put("name", name); // requestedParams.put("designation", designation); // requestedParams.put("salary", salary); Log.d("HashMap", requestedParams.get("id")); Toast.makeText(getApplicationContext(), "Success!! Employee Deleted ID : " + requestedParams.get("id"), Toast.LENGTH_LONG).show(); PostRequestHandler postRequestHandler = new PostRequestHandler(Constant.DELETE, requestedParams); postRequestHandler.execute(); listEmployee(view); } public void listEmployee(View view) { Intent intent = new Intent(EditActivity.this, ViewActivity.class); startActivity(intent); } }

이제 빌드 후 앱을 실행해 보겠습니다.
안드로이드 DB CRUD 1 - 쓰기
앱을 실행하면 처음 화면이 나타납니다. 이름. 직책, 급여를 입력하고 ADD EMPLOYEE 버튼을 클릭하면 DB에 저장되고 전체 목록을 보여줍니다.

 

안드로이드 DB CRUD 2 - 읽기
DB에 저장된 전체 목록을 불러온 화면입니다. 항목을 클릭하면 해당 항목만 불러와 수정, 삭제를 할 수 있습니다.

안드로이드 DB CRUD 3 - 수정
알바생의 급여를 수정한 후에 EDIT EMPLOYEE 버튼을 클릭하면 DB에 내용이 수정되고 수정된 내용이 포함된 전체 목록을 출력합니다.

 

안드로이드 DB CRUD 4 - 삭제
알바생을 선택한 후에 DELETE EMPLOYEE 버튼을 클릭하면 DB에서 알바생을 삭제하고 업데이트 된 전체 목록을 출력합니다.

 

감사합니다.


안드로이드를 개발할 때 유의해야 할 내용이 2가지가 있습니다.

최신 기술의 적용과 호환성 수준 입니다.

호환성을 중요하게 생각해서 낮은 레벨 기준으로 개발을 하게 되면 많은 사람들이 앱을 사용할 수는 있지만 원하는 기능을 구현하는데 한계가 발생할 수 있습니다. 그렇다고 최신 기술을 적용하면 예전 폰을 사용하는 사람들이 앱을 사용할 수 없게됩니다. 물론 시간이 지날수록 최신폰을 사용하는 사람이 늘어나겠지만 현재 기준으로 어느 수준의 앱을 개발할 지 고민할 필요가 있습니다.

안드로이드 스튜디오에서 처음 프로젝트를 생성할 때 제공하는 API Distribution 을 보면 현재 전 세계 사람들이 어느 버전의 폰을 사용하는지 확인할 수 있습니다.

이 화면은 새 프로젝트 만들기에서 최소 SDK 버전을 선택할 때 확인할 수 있습니다.

예를 들어 4.4 KitKat 버전을 최소버전으로 선택해서 개발을 한다면 전체 안드로이드 사용자 중의 약 90.1% 의 사용자가 개발 앱을 사용 가능하다는 이야기입니다.
약 9.9% 사용자는 4.4 KitKat 버전보다 낮기 때문에 앱 설치가 불가능합니다.

제가 현재 가지고 있는 안드로이드 스마트폰, 공기계의 버전은 다음과 같습니다. (2018년 6월 기준)

삼성 겔럭시 S3 - 4.4 KitKat, 업그레이드 지원 종료
삼성 겔럭시 노트2 - 4.4 KitKat, 업그레이드 지원 종료
SKT 솔폰 - 5.0 Lollipop, 업그레이드 지원 종료
Asus Nexus 7 2세대 - 6.0 Marshmallow, 업그레이드 지원 종료
삼성 겔럭시 노트5 - 7.0 Nougat
삼성 겔럭시 S6 edge - 7.0 Nougat
삼성 겔럭시 S7 edge - 8.0 Oreo, 2018. 6. 8 업데이트 확인 완료

아직까지 8.0 Oreo 버전이 탑재된 스마트폰은 사용해 보지 않아서 잘 모르겠네요.
겔럭시 S8 이상, 겔럭시 노트8 이상, LG G6, LG V30 등 최신 스마트폰에서는 경험해 볼 수 있습니다.
(구글로 잠시 검색 결과라 정확하지 않습니다. 정확한 정보가 있다면 알려주세요.)

위 화면은 2018. 5. 18, 안드로이드 스튜디오 3,1.2 기준입니다.
그리고 왼쪽의 표를 클릭하면 각 버전의 새로운 내용을 확인할 수 있습니다.
오른쪽 아래에 있는 링크를 클릭하면 자세한 내용 확인이 가능합니다.

https://developer.android.com/about/versions/android-4.0
https://developer.android.com/about/versions/android-4.1
https://developer.android.com/about/versions/android-4.2
https://developer.android.com/about/versions/android-4.3
https://developer.android.com/about/versions/android-4.4
https://developer.android.com/about/versions/android-5.0
https://developer.android.com/about/versions/android-5.1
https://developer.android.com/about/versions/marshmallow/android-6.0
https://developer.android.com/about/versions/nougat/android-7.0

4.0 이전 버전과 최신 버전(oreo 8.0 이상)은 정보가 안 나와 있네요.

이 표를 보고 어느 버전을 개발해야 할 지 결정해야겠네요.

제 개인적인 생각은 4.0 버전으로 개발을 진행하다가 특정 기능이 상위 버전에서만 가능하다면 체크 후 최소 버전을 올리는 방식으로 개발하는 것이 좋아 보입니다.

감사합니다.

안드로이드에서는 외부 데이터베이스(Mysql)에 직접 접속할 수 없습니다.


이전에는 Mysql에서 제공하는 MySQL Connector 자바 파일을 가져와서 접속이 가능했는데 보안 상 이유 때문인지 더 이상 서비스가 안된다고 하네요.


그래서 중간에 서버 프로그래밍(php 또는 node.js)를 활용하면 mysql에 접속할 수 있다고 합니다.


관련 자료를 여러가지 찾아봤는데 가장 잘 되어있는 예제를 해외 사이트에서 찾았습니다.

아래 링크를 확인해 주세요.

http://freeprojectcode.com/android/android-mysql-basic-crud-operation-tutorial-for-android-studio-project/


그래서 아래 프로젝트를 따라해 보도록 하겠습니다.


게시하신 분은 하나의 글로 끝내셨는데 이해하면서 진행하려면 아래 내용의 서비스 및 프로그램이 필요합니다.


1. MySQL, 웹 서버(아파치, IIS 등) + php


저같은 경우 최근에 구매한 Synolygy NAS를 활용해서 Mysql과 아파치+php 환경을 외부에서 접속할 수 있도록 구축해놨습니다.


2. php 에디터(드림위버, EditPlus 등)


php 에디터의 경우 무료 및 유료 프로그램이 많이 있지만 어도비 사의 드림위버를 사용하였습니다.

(영상, 사진 편집등도 하기 때문에 adobe 사의 create croud 플랜을 구독중에 있습니다.)

최근 MS에서 무료로 배포중인 visual studio code 에서 php 언어를 지원하고 있습니다.


3. 안드로이드 스튜디오


안드로이드 스튜디오는 무료로 설치 가능합니다.


위의 3가지 환경이 준비되었다면 링크의 내용을 따라해 볼 수 있습니다.

과연 어떤 프로세스로 구현되어 있을 까요?


1. MySQL에서 DB 및 Table를 생성한다.


2. PHP로 MySQL 접속, Table에 자료 쓰기, 찾기, 수정, 삭제를 할 수 있는 php파일을 생성한다.


3.안드로이드 스튜디오에서 php를 활용하여 mysql에 접속하는 화면 및 클래스를 생성한다.


아래 3개의 글을 읽고 따라해 보시기 바랍니다.


"안드로이드 DB CRUD(쓰기, 읽기, 수정, 삭제) 2 - MariaDB 설정하기" - http://ilbbang.tistory.com/45

"안드로이드 DB CRUD(쓰기, 읽기, 수정, 삭제) 3 - PHP로 MySQL에 접근하기" - http://ilbbang.tistory.com/47

"안드로이드 DB CRUD(쓰기, 읽기, 수정, 삭제) 4 - Android 화면 및 구현하기" - http://ilbbang.tistory.com/52


감사합니다.

안드로이드에서는 오디오 재생을 위해 android.media API를 제공합니다.

기본적인 플레이만 필요하다면 패키지 안에 있는 미디어플레이어 클래스를 활용하면 됩니다.


하지만 기본적인 미디어플레이어를 사용할 경우 레이턴시가 존재하기 때문에 빠른 반응속도를 요구하는 앱을 개발하기 위해서는 NDK를 사용해 볼 필요가 있어 보입니다.


NDK에 대한 내용은 아래 링크를 클릭하면 됩니다.

https://developer.android.com/ndk/guides/?hl=ko


이 글을 읽고 과연 NDK가 필요할지에 대한 고민은 직접 해보시기 바랍니다.


NDK에서 재공되는 기본 샘플 "native-audio" 를 실행해 보기 위해 NDK를 설치해 보고 안드로이드 스튜디오에서 실행해 보겠습니다.


우선 NDK를 다운로드 받아 봅니다.


아래 링크에서 자신의 컴퓨터 사양에 맞는 버전을 다운로드 합니다.

https://developer.android.com/ndk/downloads/?hl=ko


설치 방법은 Apache Maven 설치 방법과 비슷합니다.

1) zip 파일을 다운로드 받아서 프로그램 폴더에 압축을 해제합니다.

ex) "C:\Program Files\android-ndk-r17"

2) 해당 경로를 환경변수 path에 추가합니다.


설치가 완료되면 샘플 파일을 다운로드 받습니다.

아래 링크를 클릭해서 zip 파일을 다운로드 받은 후 적당한 폴더에 풀어주세요.

https://github.com/googlesamples/android-ndk


안드로이드 스튜디오에서 native audio 프로젝트를 열어봅니다.


열어보면 아래와 같은 오류 메시지가 나타나면서 실행이 되지 않습니다.


Migrate Project to Gradle?

This project does not use the Gradle build system.

We recommend that you migrate to using the Gradle build system.

More Information about migrating to Gradle

Don't show this message again.


인터넷으로 찾아보니 Gradle 형식이 아니기 때문에 나타나는 문제라고 하네요.

프로젝트를 닫고 open project가 아닌 import project로 해당 폴더를 선택해서 열어봅니다.


이번엔 다른 메시지가 나타납니다.


Error:Could not find com.android.tools.build:gradle:3.1.2.

Searched in the following locations:

https://jcenter.bintray.com/com/android/tools/build/gradle/3.1.2/gradle-3.1.2.pom

https://jcenter.bintray.com/com/android/tools/build/gradle/3.1.2/gradle-3.1.2.jar

Required by:

project :

<a href="add.google.maven.repository">Add Google Maven repository and sync project</a><a href="openFile:P:\Programming2018\AndroidStudioProjects\AIJTestProjects\native-audio\build.gradle">Open File</a>

<a href="enable.embedded.maven.repository">Enable embedded Maven repository and sync project</a>


위에 있는 Add Google Maven repository and sync project 글씨를 클릭하면 다시 빌드가 되면서 오류메시지가 사라집니다.


이제 앱 실행이 가능하게 됬네요.


하지만 실행하면 다른 오류가 발생합니다.


Error: Your project contains C++ files but it is not using a supported native build system.

Consider using CMake or ndk-build integration. For more information, go to:

 https://d.android.com/r/studio-ui/add-native-code.html

Alternatively, you can use the experimental plugin:

 https://developer.android.com/r/tools/experimental-plugin.html


SDK Manager 에서 SDK Tools 탭에 있는 CMake LLDB NDK 3가지를 설치해야 된다고 나와있네요. 3가지를 선택하고 OK 버튼을 클릭하면 안드로이드 스튜디오에 해당 Tool이 설치됩니다.


그리고 마지막으로 "Link C++ Project with Gradle" 옵션을 선택해 줘야 합니다.

새 프로젝트 생성때는 체크박스를 선택하면 되지만 기존 예제를 가져온 경우에는 

상단메뉴 File - Link C++ Project with Gradle 메뉴에서 Build System을 ndk-build를 선택한 후에 cpp 파일이 있는 폴더안에 있는 "Android.mk" 파일을 선택하고 OK버튼을 클릭하면 선택이 완료됩니다.

안드로이드 스튜디오는 안드로이드 개발을 편하게 해주는 프로그램입니다.
개발을 더욱 편하게 해주는 옵션을 설정해 주면 개발 속도가 더욱 빨라집니다.

개인적으로 편하다고 생각하는 옵션 2가지를 소개하겠습니다.


옵션1. 코드를 입력했을 때 자동으로 import 되도록 할 수 있습니다.

기본 옵션은 이 기능이 활성화 되어 있지 않습니다.
자바 코드에서 코드를 입력했을 때 새로운 내용을 import 해야 할 경우 직접 파일 상단에 import를 추가해 주거나 alt + enter 키를 쳐서 하나하나 추가해 줘야 합니다.
초반에 공부할 때는 도움이 되지만 프로젝트를 진행할 때, 파일을 만들때 마다 하나하나 추가해 줘야하는 불편함이 있습니다.
그래서 옵션에서 설정해 주면 그 다음부터는 자동으로 필요한 import를 생성해 줍니다.

설정 방법은 다음과 같습니다.

안드로이드 스튜디오 상단 메뉴에 있는 File - Settings... 를 클릭합니다.

Setting 화면 왼쪽 메뉴에서 Editor - General - Auto Import 메뉴를 클릭합니다.
오른쪽 화면에서 Java 하위 메뉴의 Add unambiguous imports on the fly 옵션과 Optimize imports on the fly (for current project) 옵션을 활성화 시켜 줍니다.


옵션2. 대소문자 구분없이 자동완성 가능하게 하기

Visual Studio 를 사용하다가 안드로이드 스튜디오를 사용하면서 불편했던 점이 대소문자가 틀리면 자동완성이 되지 않는 점이었습니다.

Visual Studio에서는 스펠링만 맞으면 자동완성이 되어 대소문자는 나중에 생각하면 됬는데 여기선 코드 작성할때 대소문자의 위치도 신경써서 작성해야 자동완성이 됩니다. 아래 옵션을 수정하면 이제 대소문자가 틀려도 스펠링만 맞으면 자동완성 옵션에서 원하는 코드를 쉽게 찾을 수 있습니다.

설정 방법은 다음과 같습니다.

안드로이드 스튜디오 상단 메뉴에 있는 File - Settings... 를 클릭합니다.

Setting 화면 왼쪽 메뉴에서 Editor - General - Code Completion 메뉴를 클릭합니다.
Case sensitive completion 을 First Letter 에서 None로 변경합니다.

감사합니다.

+ Recent posts