1. MySQL 설치

https://dev.mysql.com/downloads/mysql/

 

MySQL :: Download MySQL Community Server

Select Operating System: Select Operating System… Microsoft Windows Ubuntu Linux Debian Linux SUSE Linux Enterprise Server Red Hat Enterprise Linux / Oracle Linux Fedora Linux - Generic Oracle Solaris macOS FreeBSD Source Code Select OS Version: All Window

dev.mysql.com

위 링크에 접속 한 뒤 mysql dmg파일을 다운로드한다.

 

설치 중 데이터베이스 비밀번호 설정하는 부분이 나오는데,

나중에 필요하니 잘 기억을 해둔다.

 

설치 후 시스템 환경설정에서 mysql 의 설치를 확인 한 뒤,

Server를 구동시켜준다.

 

터미널을 켜고 mysql에 접속한다.

cd /user/local/mysql/bin

./mysql -uroot -p

위에서 설정했던 비밀번호를 입력하면

sql로 접속할 수 있다.

 

루트 계정의 비밀번호 변경은 다음과 같다.

set password = password('변경할 비밀번호');

 

 

데이터베이스 생성

create database 데이터베이스명 default charater set utf8 collate utf_general_ci;

show databases;

 

 

사용자 계정 생성 후 전체 권한

create user '유저명'@'localhost' identified by '사용할 비밀번호';

grant all privileges on 데이터베이스명.* to 유저명@localhost;

 

 

2. Workbench 설치

https://dev.mysql.com/downloads/workbench/

 

MySQL :: Download MySQL Workbench

Select Operating System: Select Operating System… Microsoft Windows Ubuntu Linux Red Hat Enterprise Linux / Oracle Linux Fedora macOS Source Code Select OS Version: All Windows (x86, 64-bit) Recommended Download: Other Downloads: Windows (x86, 64-bit), MSI

dev.mysql.com

설치 후 위에서 생성한 사용자 계정으로 접속하면 된다.

크게 어려울 것이 없어서 더 설명이 없다...

 

 

 

3. JDBC 연결

이클립스와 연결하기 위해서는 MySQL Connector 가 설치되어 있어야 한다.

https://dev.mysql.com/downloads/file/?id=476197

 

MySQL :: Begin Your Download

The world's most popular open source database

dev.mysql.com

 

mysql-connector-java-5.1.46.tar.gz를 받은 뒤, 압축을 풀어준다.

 

압축을 푼 mysql-connector-java-5.1.46-bin.jar 파일을

/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/lib/ext

 

위치에 옮긴다.

 

이후, 이클립스에서 이동시켰던 JAR 파일을 등록해준다.

 

1) eclipse로 돌아가서 환경설정을 킨다.

2) 킨 후 Java / Installed JREs 를 누른다.

3) 사용하는 jdk 를 선택하고 edit... 을 누른다.

4) add External JARs... 를 누르고 아까 ext 폴더에서 넣은 mysql jar 파일을 찾아 지정해준다.

 

 

 

 

sidongmen

어플을 개발하다보면 작은 양의 데이터를 임시적으로 기기 내부에 저장해둘 때가 있다.

내부에 저장하려는 데이터의 양이 많거나 빠른 속도를 요구할 때는 SQLite를 사용하지만

작고 간단한 String 값 몇 개 정도는 SQLite 를 사용하는 것은 무거울 수도 있다....

이럴 경우 SharedPreference라는 클래스를 사용하여 이를 처리하는 방법이 있다.

 

나의 경우에는 앱에서 로그인을 하면 서버로 부터 JWT(JSON Web Tokens)을 받아와

이를 저장하고, 이후 추가적인 로그인 없이도 exp 타임 안에 계속해서 로그인 상태가

유지되어야 했다.

 

flutter 에서도 다행히 SharedPreference를 지원하는 패키지가 있으며

이 클래스를 Flutter에서도 사용하는 방법을 기록해두려고 한다.

 

 

 

 

우선 안드로이드에서는 아래와 같이 사용한다.

 

1. 저장

SharedPreferences pref = getSharedPreferences(PREFERENCE, MODE_PRIVATE);

// SharedPreferences 의 데이터를 저장/편집을 위해 Editor 변수를 선언
SharedPreferences.Editor editor = pref.edit();

// key값에 value값을 저장.
// String, boolean, int, float, long 값 등 저장 가능
editor.putString(key, value);

// 메모리에 있는 데이터를 저장장치에 저장함. commit
editor.commit();

 

2. 불러오기

// SharedPreference 를 선언.
// 저장했을때와 같은 key로 xml에 접근.
SharedPreferences pref = getSharedPreferences(PREFERENCE, MODE_PRIVATE);

// key에 해당한 value를 불러온다.
// 두번째 매개변수는 , key에 해당하는 value값이 없을 때에는 이 값으로 대체한다.
String result = pref.getString(key, "");

 

한눈에 봐도 코드가 직관적이다.

 

SharedPreference 의 경우 Key/Value 형태로 데이터를 저장할 수 있는 데이터 구조로

내부적으로는 XML 파일로 저장이 된다.

 

flutter에서 이를 어떻게 사용해야 하는지 알아보자.

플러터의 경우 아래에 패키지를 통해 SharedPreference를 사용할 수 있다.

 

https://pub.dev/packages/shared_preferences

 

shared_preferences | Flutter Package

Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android.

pub.dev

 

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Shared preferences demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(title: 'Shared preferences demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  SharedPreferences _prefs;

  @override
  void initState() {
    super.initState();
    _loadCounter();
  }

  _loadCounter() async {
    // SharedPreferences의 인스턴스를 필드에 저장
    _prefs = await SharedPreferences.getInstance();
    setState(() {
      // SharedPreferences에 counter로 저장된 값을 읽어 필드에 저장. 없을 경우 0으로 대입
      _counter = (_prefs.getInt('counter') ?? 0);
    });
  }

  _incrementCounter() async {
    setState(() {
      // 카운터 값을 1 증가
      _counter = (_prefs.getInt('counter') ?? 0) + 1;
      // 카운터 최신 값을 SharedPreferences에 counter라는 이름으로 저장
      _prefs.setInt('counter', _counter);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text(
              // 카운터 값을 설정
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // 버튼을 누를 때 마다 _incrementCounter 메소드 호출
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

 

intState()를 통해 앱이 실행 될 시 asynchronous 로 _loadCounter() 를 실행한다.

해당 매소드는 기기 내부 장치에 데이터가 있는지 확인한 뒤, 있으면 불러오고 없으면

변수 _counter에 0을 넣어준다.

 

이후 버튼을 누르면 실행되는 _incrementCounter() 메소드 또한 이를 비동기적으로

sharedPreferece를 통해 기기에 저장한다.

 

간단하쥬~?

 

 

 

 

'프로그래밍 > Flutter' 카테고리의 다른 글

Flutter 안드로이드에서 scrollview 반짝임(glow) 제거  (0) 2020.11.04
Flutter SNS Login Package  (0) 2020.08.24
Cupertino ActionSheet  (0) 2020.04.05
image shake animation  (0) 2020.04.04
flutter_staggered_grid_view  (0) 2020.03.15

 

 

벡엔드 담당자와 협업중 자바에서 php서버로 Multipart post를 필요로 하였다.

아래의 클래스를 사용하였으며, 라이브러리는

com.google.guava_1.6.0.jar
0.91MB

구아바?

구아바!

 

 

 

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;


import com.google.common.base.Strings;
import com.google.common.io.CharStreams;

public class MultipartUploader {

    private static final String CHARSET = "UTF-8";

    private static final String CRLF = "\r\n";

    public String httpUpload(String url, String filename, byte[] byteStream)
        throws MalformedURLException, IOException {

        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        final String boundary = Strings.repeat("-", 15) + Long.toHexString(System.currentTimeMillis());

        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setUseCaches(false);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Cache-Control", "no-cache");
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

        OutputStream directOutput = connection.getOutputStream();
        PrintWriter body = new PrintWriter(new OutputStreamWriter(directOutput, CHARSET), true);

        body.append(CRLF);
        addSimpleFormData("가나다라", "atㅋㅋㅋㅇㅇtach1", body, boundary); //텍스트 파라미터
        addSimpleFormData("마바사", "6ㄴㅇㅁ", body, boundary); //텍스트 파라미터
        addFileData("attach", filename, byteStream, body, directOutput, boundary);
        addCloseDelimiter(body, boundary);

        int responseCode = connection.getResponseCode();
        String responseMessage = connection.getResponseMessage();
       
        String payload = CharStreams.toString(new InputStreamReader(connection.getInputStream()));
        return payload;
    }
    
    private static void addSimpleFormData(String paramName, String wert, PrintWriter body,
            final String boundary) {

body.append("--").append(boundary).append(CRLF);
body.append("Content-Disposition: form-data; name=\"" + paramName + "\"").append(CRLF);
body.append("Content-Type: text/plain; charset=" + CHARSET).append(CRLF);
body.append(CRLF);
body.append(wert).append(CRLF);
body.flush();
}

private static void addFileData(String paramName, String filename, byte[] byteStream, PrintWriter body,
      OutputStream directOutput, final String boundary) throws IOException {

body.append("--").append(boundary).append(CRLF);
body.append("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + filename + "\"")
.append(CRLF);
body.append("Content-Type: application/octed-stream").append(CRLF);
body.append("Content-Transfer-Encoding: binary").append(CRLF);
body.append(CRLF);
body.flush();

directOutput.write(byteStream);
directOutput.flush();

body.append(CRLF);
body.flush();
}

private static void addCloseDelimiter(PrintWriter body, final String boundary) {
body.append("--").append(boundary).append("--").append(CRLF);
body.flush();
}
    
}

 

위의 파라미터 중 byteStream은 

 

  public static byte[] fileToBinary(File file) {
	    String out = new String();
	    byte[] fileArray = null;
	    FileInputStream fis = null;
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
	 
	    try {
	        fis = new FileInputStream(file);
	    } catch (FileNotFoundException e) {
	        System.out.println("Exception position : FileUtil - fileToString(File file)");
	    }
	 
	    int len = 0;
	    byte[] buf = new byte[1024];
	    try {
	        while ((len = fis.read(buf)) != -1) {
	            baos.write(buf, 0, len);
	        }
	 
	          fileArray = baos.toByteArray();
	       // out = new String(base64Enc(fileArray));
	 
	        fis.close();
	        baos.close();
	    } catch (IOException e) {
	        System.out.println("Exception position : FileUtil - fileToString(File file)");
	    }
	 
	    return fileArray;
	}
	 
	public static byte[] base64Enc(byte[] buffer) {
	    return Base64.encodeBase64(buffer);
	}

}

를 사용한다.

fileArray를 리턴하는데 내가 급하게 만든다고 필요없는 메서드가 있긴하다...

 

'프로그래밍 > Java & JSP' 카테고리의 다른 글

Dependency Injection 이란?  (0) 2020.09.12

https://flutter.dev/docs/development/ui/widgets/cupertino

 

Cupertino (iOS-style) widgets

 

flutter.dev

showCupertinoModalPopup(
  context: context,
  builder: (BuildContext context) => CupertinoActionSheet(
      title: const Text('Choose Options'),
      message: const Text('Your options are '),
      actions: <Widget>[
        CupertinoActionSheetAction(
          child: const Text('One'),
          onPressed: () {
            Navigator.pop(context, 'One');
          },
        ),
        CupertinoActionSheetAction(
          child: const Text('Two'),
          onPressed: () {
            Navigator.pop(context, 'Two');
          },
        )
      ],
      cancelButton: CupertinoActionSheetAction(
        child: const Text('Cancel'),
        isDefaultAction: true,
        onPressed: () {
          Navigator.pop(context, 'Cancel');
        },
      )),
);

특이한 것은 안드로이드에서 cupertino 디자인이 유지된다는 점이다.

ㅋ 재밌네

'프로그래밍 > Flutter' 카테고리의 다른 글

Flutter SNS Login Package  (0) 2020.08.24
Shared Preferences  (1) 2020.04.28
image shake animation  (0) 2020.04.04
flutter_staggered_grid_view  (0) 2020.03.15
Flutter Search-bar 구현  (0) 2020.03.13

 

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart';

class ShakeAnimation extends StatefulWidget {
  @override
  _ShakeAnimationState createState() => _ShakeAnimationState();
}

class _ShakeAnimationState extends State<ShakeAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController animationController;
  Animation<double> animation;

  @override
  void initState() {
    super.initState();
    animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    )..addListener(() => setState(() {}));

    animation = Tween<double>(
      begin: 50.0,
      end: 120.0,
    ).animate(animationController);

    animationController.forward();
  }

  Vector3 _shake() {
    double progress = animationController.value;
    double offset = sin(progress * pi * 10.0);
    return Vector3(offset * 4, 0.0, 0.0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Shake animation example")),
      body: Center(
        child: Transform(
          transform: Matrix4.translation(_shake()),
          child: FlutterLogo(
            size: 60.0,
          ),
        ),
      ),
    );
  }
}

'프로그래밍 > Flutter' 카테고리의 다른 글

Shared Preferences  (1) 2020.04.28
Cupertino ActionSheet  (0) 2020.04.05
flutter_staggered_grid_view  (0) 2020.03.15
Flutter Search-bar 구현  (0) 2020.03.13
플러터 - 크로스 플랫폼  (1) 2020.03.11

+ Recent posts