- 지금까지 DB연결을 위한 Tomcat Servlet, Node.js 등을 이용해봤었다.
- MySQL과 안드로이드는 다이렉트로 연결이 안되서 웹서버(웹프로그램)를 중간에 만들어 연결해줘야한다. 앱 - 웹 - DB의 연결 구조라고 생각하면 된다.
- 주소관리 앱을 만들어서 사진까지 등록해보도록 하겠다.
- DB Table을 만들도록 하겠다.
- MySQL
- db는 어떤걸 사용해도 상관없다. 해당 db에 table을 만들겠다.
#2021.10.01
# 주소록 테이블을 만들겠다.
use sys;
create table users(
id int auto_increment primary key,
name nvarchar(20),
tel nvarchar(20),
address nvarchar(200)
);
- table에 data를 insert 해주겠다.
insert into users(name,tel,address,photo) values('송중기','010-0101-0101','인천시 미추홀구 주안동','img01.png');
insert into users(name,tel,address,photo) values('조승우','010-0202-0202','인천시 중구 신포동','img02.png');
insert into users(name,tel,address,photo) values('지성','010-0303-0303','인천시 부평구 부평동','img03.png');
insert into users(name,tel,address,photo) values('조인성','010-0404-0404','인천시 계양구 계양동','img04.png');
insert into users(name,tel,address,photo) values('현빈','010-0505-0505','인천시 강화군 강화면','img05.png');
select * from users;
- Node.js 작업을 위해 VSC Open
- Terminal open - 프로젝트 생성
C:\data\node>express -e ex10
- npm install - 라이브러리 설치
C:\data\node\ex10>npm install
- nodemon 설치
C:\data\node\ex10>npm install nodemon -g
- Mysql 설치
C:\data\node\ex10>npm install mysql
- C:\data\node\ex10\package.json
{
"name": "ex10",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"ejs": "~2.6.1",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"mysql": "^2.18.1" <<<---
}
}
- C:\data\node\ex10\routes\users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
// send로 해당 데이터 출력
res.send('respond with a resource');
});
module.exports = router;
- C:\data\node\ex10\routes\users.js
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var db = mysql.createConnection({
host:'localhost',
user:'root',
password:'1111',
database:'sys'
})
/* GET users listing. */
router.get('/', function(req, res, next) {
var sql = "select * from users";
db.query(sql,function(err,rows){
// send로 해당 데이터 출력
res.send(rows);
});
});
module.exports = router;
- 이미지를 담을 폴더를 생성하겠다. 해당 폴더에 photo 폴더에 담은 이미지를 넣는다. 이미지를 넣은 후 서버를 재시작한다.
- C:\data\node\ex10\public\(new)upload - folder
- localhost 로 접속 가능하지만 ip로도 가능하다.
- 이제 안드로이드 앱 작업을 하도록 하겠다.
- ex07이라는 새로운 프로젝트를 생성하겠다.
- build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 30 <<<---
buildToolsVersion "30.0.0" <<<---
defaultConfig {
applicationId "com.example.ex07"
minSdkVersion 26 <<<---
targetSdkVersion 30 <<<---
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions { <<<---
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.android.support:design:30.0.0' <<<---
implementation 'com.squareup.retrofit2:retrofit:2.2.0' <<<---
implementation 'com.squareup.retrofit2:converter-gson:2.2.0' <<<---
implementation 'com.squareup.picasso:picasso:2.5.2' <<<---
implementation 'de.hdodenhof:circleimageview:3.1.0' <<<---
}
- src/main/res/drawable/(new)ic_person.xml - 사람 이미지가 없을때 기본값 이미지
- src/main/java/com/example/ex07/MainActivity.java
package com.example.ex07;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("사용자관리");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_person);
}
// @Override
// public boolean onOptionsItemSelected(@NonNull MenuItem item) {
// return super.onOptionsItemSelected(item);
// }
}
- src/main/res/layout/activity_main.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=".MainActivity">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
- 메인에 들어갈 아이템 xml 생성
- src/main/res/layout/(new)item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#03A9F4"
android:padding="10sp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/photo"
android:layout_width="70sp"
android:layout_height="70sp"
android:src="@drawable/ic_person"
android:layout_marginRight="20sp"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:text="아무개"
android:textSize="20sp"
android:layout_toRightOf="@id/photo"
android:textStyle="bold"/>
<TextView
android:id="@+id/tel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:text="010-0000-0000"
android:textSize="15sp"
android:layout_toRightOf="@id/photo"
android:layout_below="@id/name"/>
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:text="뉴욕주 뉴욕시 뉴욕면"
android:textSize="15sp"
android:layout_toRightOf="@id/photo"
android:layout_below="@id/tel"/>
</RelativeLayout>
- db 연결을 위한 인터넷 권한 설정
- src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ex07">
<uses-permission android:name="android.permission.INTERNET" />
.....
</manifest>
- src/main/java/com/example/ex07/(new)User.java - java class
package com.example.ex07;
public class User {
private int id;
private String name;
private String tel;
private String address;
private String photo;
// generate getters and setters and toString
- src/main/java/com/example/ex07/MainActivity.java
package com.example.ex07;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ArrayList<User> array = new ArrayList<>();
ListView list;
UserAdapter userAdapter = new UserAdapter();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("사용자관리");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_person);
list = findViewById(R.id.list);
list.setAdapter(userAdapter);
}
class UserAdapter extends BaseAdapter{
@Override
public int getCount() {
return 5;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = getLayoutInflater().inflate(R.layout.item_user,viewGroup,false);
return view;
}
}
}
- 네트워크 접속을 위한 인터페이스 생성
- src/main/java/com/example/ex07/(new)Remote.java - Interface
package com.example.ex07;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
public interface Remote {
public static final String URL="http://192.168.0.27:3000/";
//사용자목록
@GET("users")
Call<List<User>> listUser();
}
- src/main/java/com/example/ex07/MainActivity.java
package com.example.ex07;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import static com.example.ex07.Remote.URL;
public class MainActivity extends AppCompatActivity {
List<User> array=new ArrayList<>();
ListView list;
UserAdapter userAdapter = new UserAdapter();
Remote remote;
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("사용관리");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_person);
list = findViewById(R.id.list);
list.setAdapter(userAdapter);
retrofit=new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create()).build();
remote = retrofit.create(Remote.class);
Call<List<User>> call=remote.listUser();
call.enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
array = response.body();
userAdapter.notifyDataSetChanged();
System.out.println("...................." +array.size());
}
@Override
public void onFailure(Call<List<User>> call, Throwable t) {
System.out.println("error............." + t.toString());
}
});
}
class UserAdapter extends BaseAdapter{
@Override
public int getCount() {
return array.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.item_user, parent, false);
User user=array.get(position);
TextView name=convertView.findViewById(R.id.name);
name.setText(user.getName());
TextView tel=convertView.findViewById(R.id.tel);
tel.setText(user.getTel());
TextView address=convertView.findViewById(R.id.address);
address.setText(user.getAddress());
CircleImageView photo=convertView.findViewById(R.id.photo);
Picasso.with(MainActivity.this).load(URL+"/upload/" + user.getPhoto()).into(photo);
return convertView;
}
}
}
- src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ex07">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"> <<<---
.....
- 만약 이미지가 없다면
.....
@Override
public View getView(int position, View convertView, ViewGroup parent) {
.....
CircleImageView photo=convertView.findViewById(R.id.photo);
if(user.getPhoto()==null || user.getPhoto().equals("")){
photo.setImageResource(R.drawable.ic_person);
}else {
Picasso.with(MainActivity.this).load(URL+"/upload/" + user.getPhoto()).into(photo);
}
return convertView;
}
.....
- 이제 회원 item을 클릭시 해당 정보로 이동할 수 있도록 하겠다. 우선 기본 액티비티를 만들겠다.
- src/main/java/com/example/ex07/(new)ReadActivity.java
package com.example.ex07;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
public class ReadActivity extends AppCompatActivity {
int id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read);
Intent intent = getIntent();
id = intent.getIntExtra("id",0);
getSupportActionBar().setTitle("사용자정보");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
}
- src/main/res/layout/item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#03A9F4"
android:padding="10sp"
android:id="@+id/item">
.....
- src/main/java/com/example/ex07/MainActivity.java
.....
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.item_user, parent, false);
User user=array.get(position);
TextView name=convertView.findViewById(R.id.name);
name.setText(user.getName());
TextView tel=convertView.findViewById(R.id.tel);
tel.setText(user.getTel());
TextView address=convertView.findViewById(R.id.address);
address.setText(user.getAddress());
CircleImageView photo=convertView.findViewById(R.id.photo);
if(user.getPhoto()==null || user.getPhoto().equals("")){
photo.setImageResource(R.drawable.ic_person);
}else {
Picasso.with(MainActivity.this).load(URL+"/upload/" + user.getPhoto()).into(photo);
}
RelativeLayout item = convertView.findViewById(R.id.item); <<<---
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,ReadActivity.class);
intent.putExtra("id",user.getId());
startActivity(intent);
}
});
return convertView;
}
}
}
- src/main/res/layout/(new)activity_read.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=".ReadActivity"
android:background="#CE000000"
android:padding="20sp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/photo"
android:layout_width="250sp"
android:layout_height="250sp"
android:src="@drawable/ic_person_250"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20sp"
android:layout_marginTop="50sp"/>
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="이름"
android:textColorHint="#ffffff"
android:textColor="#ffffff"
android:layout_below="@id/photo"
android:layout_marginBottom="20sp"
android:padding="10sp"/>
<EditText
android:id="@+id/tel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="전화번호"
android:textColorHint="#ffffff"
android:textColor="#ffffff"
android:layout_below="@id/name"
android:layout_marginBottom="20sp"
android:padding="10sp"/>
<EditText
android:id="@+id/address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="주소"
android:textColorHint="#ffffff"
android:textColor="#ffffff"
android:layout_below="@id/tel"
android:layout_marginBottom="20sp"
android:padding="10sp"/>
</RelativeLayout>
- 이제 read 결과를 해당 액티비티에 출력하도록 하겠다.
- VSC
- C:\data\node\ex10\routes\users.js
.....
// 사용자 정보 가지고 오기
router.get('/read', function(req,res){
var id = parseInt(req.query.id);
var sql = "select * from users where id=?";
db.query(sql,[id],function(err,rows){
res.send(rows[0]);
});
});
module.exports = router;
- 안드로이드 스튜디오
- 서버로 부터 정보 읽어오기
- src/main/java/com/example/ex07/Remote.java
.....
//사용자정보
@GET("users/read")
Call<User> readUser(@Query("id") int id);
}
- src/main/java/com/example/ex07/ReadActivity.java
.....
public class ReadActivity extends AppCompatActivity {
int id;
EditText name,tel,address; <<<---
CircleImageView photo; <<<---
Remote remote; <<<---
Retrofit retrofit; <<<---
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read);
Intent intent = getIntent();
id = intent.getIntExtra("id",0);
getSupportActionBar().setTitle("사용자정보");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
name = findViewById(R.id.name); <<<---
tel = findViewById(R.id.tel); <<<---
address = findViewById(R.id.address); <<<---
photo = findViewById(R.id.photo); <<<---
// 이하 <<<---
retrofit = new Retrofit.Builder().baseUrl(URL).addConverterFactory(GsonConverterFactory.create()).build();
remote = retrofit.create(Remote.class);
Call<User> call = remote.readUser(id);
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
System.out.println("............."+response.body());
User user = response.body();
name.setText(user.getName());
tel.setText(user.getTel());
address.setText(user.getAddress());
Picasso.with(ReadActivity.this).load(URL+"/upload/"+user.getPhoto()).into(photo);
}
@Override
public void onFailure(Call<User> call, Throwable t) {
System.out.println("............."+t.toString());
}
});
}
.....
- 이제 입력, 수정, 삭제 작업을 해보도록 하겠다.
- update - VSC
- C:\data\node\ex10\routes\users.js
.....
// post user update
router.post('/update', function(req,res){
var id = parseInt(req.query.id);
var name = req.query.name;
var tel = req.query.tel;
var address = req.query.address;
var sql = "update users set name=?,tel=?,address=? where id=?";
db.query(sql,[name,tel,address,id], function(err,rows){
res.send(rows);
})
})
module.exports = router;
- 안드로이드 스튜디오
- src/main/res/drawable/(new)ic_baseline_update_24.xml
- src/main/res/layout/activity_read.xml
.....
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_update_24"
android:backgroundTint="#3F51B5"
android:layout_marginBottom="20sp"
android:layout_marginRight="20sp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"/>
</RelativeLayout>
- src/main/java/com/example/ex07/Remote.java
.....
//사용자정보 수정
@POST("users/update")
Call<Void> updateUser(@Query("id") int id,
@Query("name") String name,
@Query("tel") String tel,
@Query("address") String address);
}
- src/main/java/com/example/ex07/MainActivity.java
.....
public class MainActivity extends AppCompatActivity {
List<User> array=new ArrayList<>();
ListView list;
UserAdapter userAdapter = new UserAdapter();
Remote remote;
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("사용자관리");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_person);
list = findViewById(R.id.list);
list.setAdapter(userAdapter);
retrofit=new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create()).build();
remote = retrofit.create(Remote.class);
readUsers(); <<<---
}
class UserAdapter extends BaseAdapter{
@Override
public int getCount() {
return array.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.item_user, parent, false);
User user=array.get(position);
TextView name=convertView.findViewById(R.id.name);
name.setText(user.getName());
TextView tel=convertView.findViewById(R.id.tel);
tel.setText(user.getTel());
TextView address=convertView.findViewById(R.id.address);
address.setText(user.getAddress());
CircleImageView photo=convertView.findViewById(R.id.photo);
if(user.getPhoto()==null || user.getPhoto().equals("")){
photo.setImageResource(R.drawable.ic_person);
}else {
Picasso.with(MainActivity.this).load(URL+"/upload/" + user.getPhoto()).into(photo);
}
RelativeLayout item = convertView.findViewById(R.id.item);
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,ReadActivity.class);
intent.putExtra("id",user.getId());
startActivity(intent);
}
});
return convertView;
}
}
// read method 만들기 <<<---
public void readUsers(){
Call<List<User>> call=remote.listUser();
call.enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
array = response.body();
userAdapter.notifyDataSetChanged();
System.out.println("...................." +array.size());
}
@Override
public void onFailure(Call<List<User>> call, Throwable t) {
System.out.println("error............." + t.toString());
}
});
}
@Override <<<---
protected void onRestart() {
super.onRestart();
readUsers();
}
}
- 이제 수정을 할 수 있도록 하겠다.
- src/main/java/com/example/ex07/ReadActivity.java
.....
});
FloatingActionButton update = findViewById(R.id.update);
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder box = new AlertDialog.Builder(ReadActivity.this);
box.setMessage("수정하시겠습니까?");
box.setNegativeButton("아니오",null);
box.setPositiveButton("예",null);
box.show();
}
});
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
}
});
FloatingActionButton update = findViewById(R.id.update);
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder box = new AlertDialog.Builder(ReadActivity.this);
box.setMessage("수정하시겠습니까?");
box.setNegativeButton("아니오",null);
box.setPositiveButton("예", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String strName = name.getText().toString();
String strTel = tel.getText().toString();
String strAddress = address.getText().toString();
Call<Void> call = remote.updateUser(id,strName,strTel,strAddress);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
finish();
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
System.out.println("........."+t.toString());
}
});
}
});
box.show();
}
});
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
}
- src/main/res/drawable/(new)ic_baseline_delete_24.xml
- src/main/res/(new)menu/(new)read.xml
<?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:title="삭제"
android:id="@+id/delete"
android:icon="@drawable/ic_baseline_delete_24"
app:showAsAction="always"/>
</menu>
- src/main/java/com/example/ex07/ReadActivity.java
.....
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.delete:
AlertDialog.Builder box = new AlertDialog.Builder(this);
box.setMessage("삭제하시겠습니까?");
box.setNegativeButton("아니오", null);
box.setPositiveButton("예", null);
box.show();
break;
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.read,menu);
return super.onCreateOptionsMenu(menu);
}
}
- VSC
- C:\data\node\ex10\routes\users.js
.....
// post user delete
router.post('/delete',function(req,res){
var id = parseInt(req.query.id);
var sql = "delete from users where id=?";
db.query(sql,[id],function(err,rows){
res.send(rows);
})
})
module.exports = router;
- 안드로이드 스튜디오
- src/main/java/com/example/ex07/Remote.java
.....
//사용자 삭제
@POST("users/delete")
Call<Void> deleteUser(@Query("id") int id);
}
- src/main/java/com/example/ex07/ReadActivity.java
.....
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.delete:
AlertDialog.Builder box = new AlertDialog.Builder(this);
box.setMessage("삭제하시겠습니까?");
box.setNegativeButton("아니오", null);
box.setPositiveButton("예", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Call<Void> call = remote.deleteUser(id);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
finish();
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
System.out.println("삭제 오류 : " +t.toString());
}
});
}
});
box.show();
break;
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
.....
- 이제 Insert하는 작업을 해보겠다.
- VSC
- C:\data\node\ex10\routes\users.js
.....
// post user insert
router.post('/insert',function(req,res){
var name = req.query.name;
var tel = req.query.tel;
var address = req.query.address;
var sql = "insert into users(name,tel,address) values(?,?,?)"
db.query(sql,[name,tel,address],function(err,rows){
res.send(rows);
})
})
module.exports = router;
- AndStu
- src/main/java/com/example/ex07/Remote.java
.....
//사용자 등록
@POST("users/insert")
Call<Void> insertUser(@Query("name") String name,
@Query("tel") String tel,
@Query("address") String address);
}
- MainActivity에 insert 버튼 추가
- src/main/res/drawable/(new)ic_baseline_add_24.xml
- src/main/res/layout/activity_main.xml
.....
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#3F51B5"
android:src="@drawable/ic_baseline_add_24"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="20sp"
android:layout_marginRight="20sp"/>
</RelativeLayout>
- src/main/java/com/example/ex07/(new)InsertActivity.java
package com.example.ex07;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
public class InsertActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read);
getSupportActionBar().setTitle("사용자등록");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
}
- src/main/java/com/example/ex07/MainActivity.java
.....
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("사용자관리");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_person);
list = findViewById(R.id.list);
list.setAdapter(userAdapter);
retrofit=new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create()).build();
remote = retrofit.create(Remote.class);
readUsers();
FloatingActionButton insert = findViewById(R.id.insert); <<<---
insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, InsertActivity.class);
startActivity(intent);
}
});
}
.....
- src/main/java/com/example/ex07/InsertActivity.java
.....
public class InsertActivity extends AppCompatActivity {
// 입력값 변수 설정
EditText name, tel, address;
Remote remote;
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read);
getSupportActionBar().setTitle("사용자등록");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
name = findViewById(R.id.name);
tel = findViewById(R.id.tel);
address = findViewById(R.id.address);
retrofit = new Retrofit.Builder().baseUrl(URL).addConverterFactory(GsonConverterFactory.create()).build();
remote = retrofit.create(Remote.class);
FloatingActionButton insert = findViewById(R.id.update);
insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String strName = name.getText().toString();
String strTel = tel.getText().toString();
String strAddress = address.getText().toString();
if(strName.equals("") || strTel.equals("") || strAddress.equals("")){
Toast.makeText(InsertActivity.this,"내용을 입력하세요.",Toast.LENGTH_SHORT).show();
}else{
AlertDialog.Builder box = new AlertDialog.Builder(InsertActivity.this);
box.setMessage("사용자를 등록하시겠습니까?");
box.setNegativeButton("아니오",null);
box.setPositiveButton("예", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Call<Void> call = remote.insertUser(strName,strTel,strAddress);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
finish();
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
System.out.println("insert 오류"+t.toString());
}
});
}
});
box.show();
}
}
});
}
.....
- 이미지 업로드를 해보겠다.
- 엘범에 있는 데이터를 가지고와서 업로드 해보겠다.
- src/main/java/com/example/ex07/InsertActivity.java
.....
public class InsertActivity extends AppCompatActivity {
// 입력값 변수 설정
EditText name, tel, address;
Remote remote;
Retrofit retrofit;
// 이미지 저장을 위한 변수
CircleImageView photo; <<<---
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read);
getSupportActionBar().setTitle("사용자등록");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
name = findViewById(R.id.name);
tel = findViewById(R.id.tel);
address = findViewById(R.id.address);
photo = findViewById(R.id.photo); <<<---
photo.setOnClickListener(new View.OnClickListener() { // InsertActivity의 이미지 클릭시
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}
});
.....
- 엘범에서 가지고온 이미지 파일을 업로드하기 위한 권한설정을 해주겠다.
- src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ex07">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
.....
- 최초 실행시 스토리지 접근 권한 여부를 물어보도록 하겠다.
- src/main/java/com/example/ex07/MainActivity.java
public class MainActivity extends AppCompatActivity {
List<User> array=new ArrayList<>();
ListView list;
UserAdapter userAdapter = new UserAdapter();
Remote remote;
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 최초실행시 권한 여부 물음
permissionCheck(); <<<---
.....
@Override
protected void onRestart() {
super.onRestart();
readUsers();
}
public void permissionCheck(){
String[] permissions= {Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA };
ArrayList<String> checkPermission=new ArrayList<>();
for(String permission:permissions){
if(ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED){
checkPermission.add(permission);
}
}
if(checkPermission.size() > 0){
String[] reqPermission=checkPermission.toArray(new String[checkPermission.size()]);
ActivityCompat.requestPermissions(this, reqPermission,100);
}
}
}
- src/main/java/com/example/ex07/InsertActivity.java
.....
public class InsertActivity extends AppCompatActivity {
// 입력값 변수 설정
EditText name, tel, address;
Remote remote;
Retrofit retrofit;
// 이미지 저장을 위한 변수
CircleImageView photo;
String strFile;
.....
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if(requestCode==0){
// photo.setImageURI(data.getData());
try {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(data.getData(),projection,null,null,null);
cursor.moveToNext();
strFile = cursor.getString(cursor.getColumnIndex(projection[0]));
// 안드로이드는 비트맺으로 읽어봐야 업로드가 가능하다.
photo.setImageBitmap(BitmapFactory.decodeFile(strFile));
cursor.close();
}catch (Exception e){
System.out.println("error : "+e.toString());
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
}
- 이제 사진을 DB 업로드 하는 작업을 하도록 하겠다.
- VSC
- 이미지 업로드를 위한 라이브러리 multer를 터미널에서 설치해주겠다.
C:\data\node\ex10> npm install multer
- C:\data\node\ex10\routes\users.js
.....
// 이미지 업로드 및 파일명 설정
var multer = require('multer');
var upload = multer({
storage: multer.diskStorage({
destination:(req,file,done) =>{
done(null, './public/upload');
},
filename:(req,file,done) =>{
done(null, Date.now()+'_'+file.originalname);
}
})
});
// post user insert
router.post('/insert',upload.single('photo'), function(req,res){
var name = req.body.name;
var tel = req.body.tel;
var address = req.body.address;
var photo = req.file.filename;
var sql = "insert into users(name,tel,address,photo) values(?,?,?,?)"
db.query(sql,[name,tel,address,photo],function(err,rows){
res.send(rows);
})
})
module.exports = router;
- AndStu
- src/main/java/com/example/ex07/Remote.java
.....
// insert 수정하여 아래와 같이 한다.
//사용자 등록 + 이미지 업로드
@POST("users/insert")
Call<Void> uploadUser(@Part("name") RequestBody name,
@Part("tel") RequestBody tel,
@Part("address") RequestBody address,
@Part MultipartBody.Part photo);
}
- src/main/java/com/example/ex07/InsertActivity.java
.....
FloatingActionButton insert = findViewById(R.id.update);
insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String strName = name.getText().toString();
String strTel = tel.getText().toString();
String strAddress = address.getText().toString();
if(strName.equals("") || strTel.equals("") || strAddress.equals("")){
Toast.makeText(InsertActivity.this,"내용을 입력하세요.",Toast.LENGTH_SHORT).show();
}else{
AlertDialog.Builder box = new AlertDialog.Builder(InsertActivity.this);
box.setMessage("사용자를 등록하시겠습니까?");
box.setNegativeButton("아니오",null);
box.setPositiveButton("예", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
File file=new File(strFile);
System.out.println("strFile................." + strFile);
RequestBody reqFile=RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part partFile=MultipartBody.Part.createFormData("photo", file.getName(), reqFile);
RequestBody reqName=RequestBody.create(MediaType.parse("multipart/form-data"),strName);
RequestBody reqTel=RequestBody.create(MediaType.parse("multipart/form-data"),strTel);
RequestBody reqAddress=RequestBody.create(MediaType.parse("multipart/form-data"),strAddress);
Call<Void> call = remote.uploadUser(reqName,reqTel,reqAddress,partFile);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
finish();
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
System.out.println("insert 오류"+t.toString());
}
});
}
});
box.show();
}
}
});
.....
'ICIA 수업일지' 카테고리의 다른 글
2021.10.06 수업일지(Spring Framework 이용 게시판 만들기) (0) | 2021.10.06 |
---|---|
2021.10.05 수업일지(Spring Framework 시작) (0) | 2021.10.05 |
2021.09.30 수업일지(안드로이드 개발 기초, Firebase) (0) | 2021.09.30 |
2021.09.29 수업일지(안드로이드 개발 기초, Kakao API, Google API) (0) | 2021.09.29 |
2021.09.28 수업일지(안드로이드 기초, SQLite) (0) | 2021.09.28 |