안드로이드를 개발할 때 유의해야 할 내용이 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 버전으로 개발을 진행하다가 특정 기능이 상위 버전에서만 가능하다면 체크 후 최소 버전을 올리는 방식으로 개발하는 것이 좋아 보입니다.

감사합니다.

이 글은 제가 검색하는 과정도 포함되어 있습니다.

윈도우에서 파일의 정보를 가져오기 위해서 기본적으로 사용하고 있는 클래스는 FileInfo 입니다.
하지만 어느 카메라로 찍었는지, 어디서 찍었는지 등에 대한 정보를 확인하기 위해서는 MetaData를 확인해야 합니다.

그래서 구글에서 검색을 시작하였습니다. 처음으로 검색한 단어는 "read image metadata c#" 입니다.
관련 코드를 쉽게 찾을 수 있었습니다.

출처: Reading data metadata from JPEG, XMP or EXIF in C#
주소: https://stackoverflow.com/questions/2280948/reading-data-metadata-from-jpeg-xmp-or-exif-in-c-sharp?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

위 제공된 코드는 아래와 같습니다.

    public string GetDate(FileInfo f)
    {
        using(FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BitmapSource img = BitmapFrame.Create(fs);
            BitmapMetadata md = (BitmapMetadata)img.Metadata;
            string date = md.DateTaken;
            Console.WriteLine(date);
            return date;
        }
    }

그래서 Visual Studio 에서 바로 실행해 보기로 했습니다.

1. Visual Studio(2017 기준) 를 실행하고 새로운 프로젝트를 생성합니다.
상단 메뉴의 파일(F) - 새로 만들기(N) - 프로젝트(P) 를 선택합니다.

좌측 메뉴에 Visual C# - Windows 클래식 바탕화면을 선택하고 가운데 메뉴에 Windows Forms 앱(,net Framework)를 선택합니다.
앱 이름은 WindowsFormsGetMetaData 로 정하겠습니다. 폴더는 원하는 위치를 지정해 주세요. 아래 그림과 같이 설정이 끝났으면 확인 버튼을 클릭합니다.

폼 이름 및 크기를 바꿔볼께요.
폼을 선택하고 속성 도구를 열고 Text와 Size 속성을 바꿉니다.
(Name): Form1 - Text: 메타데이터 읽기 / Size: 400, 600

다음에 컨트톨을 추가해 보겠습니다.
도구 상자탭을 선택하고 원하는 도구 상자를 드래그해서 폼 안에 넣으면 됩니다.

저는 아래와 같이 넣었습니다.

각 도구의 주요 속성은 다음과 같습니다.

버튼(Button) - (Name): button1 / Location: 20, 20 / AutoSize: False / Size: 75, 23 / Text: 파일 선택
라벨(Label) - (Name): label1 / Location: 20, 60 / AutoSize: True / Size: 73, 12(자동으로 설정됨) / Text: 선택된 파일:
라벨(Label) - (Name): label2 / Location: 100, 60 / AutoSize: True / Size: 29, 12(자동으로 설정됨) / Text: 없음
자료보기창(DataGridView) - (Name): dataGridView1 / Location: 20, 90 / AutoSize: False / Size: 350, 450

외형을 완성했으면 이제 프로그래밍을 해보겠습니다.
폴더 선택 버튼을 더블클릭하면 자동으로 이벤트가 추가되고 코드보기 화면으로 전환됩니다.

우선 버튼 클릭 부분에는 OpenFileDialog 를 생성해서 파일이 있으면 파일명을 MessageBox에서 보여주도록 코드를 작성하였습니다.

버튼클릭 이벤트 아래쪽에 위에서 찾은 코드를 복사합니다. 우선 FileInfo 는 using System.IO; 를 활용해서 불러옵니다.
이렇게 하면 아래 그림과 같이 오류가 발생합니다.

이제부터 오류가 발생하는 부분을 찾아보겠습니다.

BitmapSource 를 구글에서 찾아보니 아래 링크에서 해당 클래스 정보를 확인할 수 있습니다.
제목: BitmapSource 클래스
네임스페이스:   System.Windows.Media.Imaging
어셈블리:  PresentationCore(PresentationCore.dll에 있음)
https://msdn.microsoft.com/ko-kr/library/system.windows.media.imaging.bitmapsource(v=vs.110).aspx

위 내용을 보면 PresentationCore 어셈블리를 추가하면 될 것으로 보입니다.
아래 그림과 같이 솔루션 탐색기에서 참조에 마우스를 대고 오른쪽 버튼을 클릭한 후에 참조 추가 메뉴를 클릭합니다.

오른쪽 어셈블리에서 프레임워크를 선택하고 오른쪽 검색창에 "presentationcore" 를 검색하면 결과가 하나만 나타납니다.
추가하려면 이름 옆에 있는 체크박스를 클릭해서 체크표시 한 후에 확인 버튼을 클릭하면 PresentationCore 어셈블리를 사용할 수 있습니다.

그리고 코딩 파일에 "using System.Windows.Media.Imaging;" 을 입력해서 해당 네임 스페이스를 불러옵니다.
그러면 BitmapSource, BitmapFrame, BitmapMetadata 사용이 가능합니다. 하지만 여전히 "BitmapFrame.Create" 부분에서 오류가 발생하네요.
오류 내용은 다음과 같습니다.

'Freezable' 형식이 참조되지 않은 어셈블리에 정의되었습니다. 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 어셈블리에 참조를 추가해야 합니다.

이 부분도 동일하게 해결 가능합니다.

솔루션 탐색기에서 참조에 마우스를 대고 오른쪽 버튼을 클릭한 후에 참조 추가 메뉴를 클릭합니다.
오른쪽 어셈블리에서 프레임워크를 선택하고 오른쪽 검색창에 "windowsbase" 를 검색하면 결과가 하나만 나타납니다.
추가하려면 이름 옆에 있는 체크박스를 클릭해서 체크표시 한 후에 확인 버튼을 클릭하면 WindowsBase 어셈블리를 사용할 수 있습니다.

이제 오류는 다 잡았습니다. 지금부터는 원하는 정보를 가져와서 DataGridView에 보여주면 되겠네요.
메서드1. 위에 제공된 코드를 아래와 같이 수정합니다. 기존 코드는 파일을 만든 날짜만 확인하였는데 전 확인 가능한 모든 속성을 가져오겠습니다.

        /// <summary>
        /// 선택한 파일의 메타데이터를 DataTable 형식으로 보냅니다.
        /// </summary>
        /// <param name="f">자료를 가져올 파일의 FileInfo를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetDate(FileInfo f)
        {
            using (FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) // 선택된 파일의 FileStream 을 생성합니다. 
            {
                DataTable dt1 = new DataTable(); // 새로운 DataTable을 생성합니다.
                dt1.Columns.Add("attribute"); // 속성 이름을 저장합니다.
                dt1.Columns.Add("value"); // 속성 값을 저장합니다.

                BitmapSource img = BitmapFrame.Create(fs); // 선택된 파일의 FileStream 를 활용하여 BitmapSource 를 생성합니다.
                BitmapMetadata md = (BitmapMetadata)img.Metadata; // 

                // BitmapMetadata 에서 제공하는 모든 속성 값을 불러옵니다. 시작
                // https://msdn.microsoft.com/ko-kr/library/system.windows.media.imaging.bitmapmetadata(v=vs.110).aspx
                dt1.Rows.Add("ApplicationName", md.ApplicationName);
                dt1.Rows.Add("Author", md.Author);
                dt1.Rows.Add("CameraManufacturer", md.CameraManufacturer);
                dt1.Rows.Add("CameraModel", md.CameraModel);
                dt1.Rows.Add("CanFreeze", md.CanFreeze);
                dt1.Rows.Add("Comment", md.Comment);
                dt1.Rows.Add("Copyright", md.Copyright);
                dt1.Rows.Add("DateTaken", md.DateTaken);
                dt1.Rows.Add("DependencyObjectType", md.DependencyObjectType);
                dt1.Rows.Add("Dispatcher", md.Dispatcher);
                dt1.Rows.Add("Format", md.Format);
                dt1.Rows.Add("IsFixedSize", md.IsFixedSize);
                dt1.Rows.Add("IsFrozen", md.IsFrozen);
                dt1.Rows.Add("IsReadOnly", md.IsReadOnly);
                dt1.Rows.Add("IsSealed", md.IsSealed);
                dt1.Rows.Add("Keywords", md.Keywords);
                dt1.Rows.Add("Location", md.Location);
                dt1.Rows.Add("Rating", md.Rating);
                dt1.Rows.Add("Subject", md.Subject);
                dt1.Rows.Add("Title", md.Title);
                // BitmapMetadata 에서 제공하는 모든 속성 값을 불러옵니다. 끝

                return dt1;
            }
        }


매서드2. 위에서 제공된 결과를 DataGridView 컨트롤에서 볼 수 있도록 가져옵니다.

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            dgv1.Rows.Clear(); // 이전 정보가 있을 경우, 모든 행을 삭제합니다.
            dgv1.Columns.Clear(); // 이전 정보가 있을 경우, 모든 열을 삭제합니다.

            foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
            {
                dgv1.Columns.Add(dc1.ColumnName, dc1.ColumnName); // 출력할 DataGridView에 열을 추가합니다.
            }

            int row_index = 0; // 행 인덱스 번호(초기 값)
            foreach (DataRow dr1 in dt1.Rows) // 선택한 파일 목록이 들어있는 DataTable의 모든 행을 스캔합니다.
            {
                dgv1.Rows.Add(); // 빈 행을 하나 추가합니다.
                foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
                {
                    dgv1.Rows[row_index].Cells[dc1.ColumnName].Value = dr1[dc1.ColumnName]; // 선택 행 별로, 스캔하는 열에 해당하는 셀 값을 입력합니다.
                }
                row_index++; // 다음 행 인덱스를 선택하기 위해 1을 더해줍니다.
            }

            foreach (DataGridViewColumn drvc1 in dgv1.Columns) // 결과를 출력할 DataGridView의 모든 열을 스캔합니다.
            {
                drvc1.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // 선택 열의 너비를 자동으로 설정합니다.
            }
        }

위에서 만든 2개의 매서드를 활용하여 버튼클릭 이벤트를 아래와 같이 수정합니다.

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // 새로운 OpenFileDialog 를 생성합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 정상적으로 선택되었을 경우에 동작합니다.
            {
                label2.Text = openFileDialog1.FileName; // 선택된 파일을 label2에 출력합니다.
                FileInfo f = new FileInfo(openFileDialog1.FileName); // 파일 전체 경로로 해당 파일의 FileInfo를 생성합니다.
                DataTable dt_metadata = GetDate(f);
                ShowDataFromDataTableToDataGridView(dt_metadata,dataGridView1);
            }
        }

전체 코드는 아래와 같습니다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO;
using System.Windows.Media.Imaging;

namespace WindowsFormsGetMetaData
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // 새로운 OpenFileDialog 를 생성합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 정상적으로 선택되었을 경우에 동작합니다.
            {
                label2.Text = openFileDialog1.FileName; // 선택된 파일을 label2에 출력합니다.
                FileInfo f = new FileInfo(openFileDialog1.FileName); // 파일 전체 경로로 해당 파일의 FileInfo를 생성합니다.
                DataTable dt_metadata = GetDate(f);
                ShowDataFromDataTableToDataGridView(dt_metadata,dataGridView1);
            }
        }

        /// <summary>
        /// 선택한 파일의 메타데이터를 DataTable 형식으로 보냅니다.
        /// </summary>
        /// <param name="f">자료를 가져올 파일의 FileInfo를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetDate(FileInfo f)
        {
            생략(매서드1)
        }

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            생략(매서드2)
        }

    }
}

이제 실행해 보겠습니다.
실행하면 다음과 같이 나타납니다.

메타데이터가 있는 그림파일을 선택하면 다음과 같이 읽어오는 것을 볼 수 있습니다.

하지만 윈도우 탐색기에서 파일 선택해서 마우스 오른쪽 버튼 클릭 후 속성 클릭 후 자세히 보기에 나타나는 정보는 기본적으로 제공하는 MetaData 보다 많은 것을 확인할 수 있습니다. 이 부분에 대해 아시는 분 있으면 댓글 남겨주세요. 저도 관련 정보를 더 찾아보도록 하겠습니다.

감사합니다.

mysql 쿼리문을 활용하여 기본적인 DB, Table 생성, 자료 쓰기 및 읽기 명령어를 소개합니다.

1. DB 생성하기

[문법]
create database DB이름
[예제]
create database test #이름이 test인 DB 생성

2. Table 만들기

[문법]
create table Table이름(열1이름 열1형식, 열2이름 열2형식, ...);
[예제]
create table humaninfo(name varchar(50), yearmonthday varchar(8), age int, address varchar(200)); #이름이 humaninfo인 Table생성
#열1이름: name, 열1형식: 글자(50자이내)
#열2이름: yearmonthday, 열2형식: 글자(8자이내)
#열3이름: age, 열3형식: 정수
#열4이름: name, 열4형식: 글자(200자이내)

3. Table에 자료 쓰기

[문법]
insert into Table이름 values(열1값, 열2값, ...);
[예제]
insert into hummaninfo values('강인한', '19840831', 33, '서울시 강서구 화곡동'); #hummaninfo Table에 자료 쓰기
# name: 강인한, yearmonthday: 19840831, age: 33, address: 서울시 강서구 화곡동
insert into hummaninfo values('김길동', '19920910', 25, '경기도 김포시 풍무동'); #hummaninfo Table에 자료 쓰기
# name: 김길동, yearmonthday: 19920910, age: 25, address: 경기도 김포시 풍무동

4. Table 자료 읽기

[문법]
select * from Table이름;
[예제]
select * from hummaninfo; # hummaninfo Table의 모든 자료 읽기

감사합니다.

MySQL DB의 자료를 안드로이드 앱에서 사용하기 위해서는 중간에 php 또는 node.js 등의 서버 프로그래밍을 거쳐야 합니다.


그래서 이번에는 mysql DB 내용을 php를 활용하여 json 형식으로 가져오는 코딩을 해보겠습니다.


과정은 간단합니다. php 파일 하나만 만들면 되는데요.

php 코드는 다음과 같습니다.

<?php 
// DB 접속 
$con=mysqli_connect("DB접속도메인또는IP:포트(3306이아닌경우)","DB사용자ID","비밀번호","사용할DB"); 
// 접속 실패 시 메시지 나오게 하기 
if (mysqli_connect_errno($con)) 
{ echo "MySQL접속 실패: " . mysqli_connect_error(); } 

// 기본 클라이언트 문자 집합 설정하기 
mysqli_set_charset($con,"utf8"); 
// 쿼리문 실행, 결과를 res에 저장 
$res = mysqli_query($con, "select * from humaninfo"); 
// 결과를 배열로 변환하기 위한 변수 정의
$result = array(); 
// 쿼리문의 결과(res)를 배열형식으로 변환(result) 
while($row = mysqli_fetch_array($res)) 
{ array_push($result, array('name'=>$row[0],'yearmonthday'=>$row[1],'age'=>$row[2],'address'=>$row[3])); } 
// 배열형식의 결과를 json으로 변환 
echo json_encode(array("result"=>$result),JSON_UNESCAPED_UNICODE); 
// DB 접속 종료 
mysqli_close($con); 
?>

해당 파일을 서버에 올리고 실행하면 다음과 같이 결과가 출력됩니다.

{"result":[{"name":"강인한","yearmonthday":"19840831","age":"33","address":"서울시 강서구 화곡동"},{"name":"김길동","yearmonthday":"19920910","age":"25","address":"경기도 김포시 풍무동"}]}

이제 이 내용을 안드로이드에서 읽어오면 됩니다.

감사합니다.

Visual Studio Code 에서 PHP 프로그래밍 및 디버그를 해보겠습니다.


Visual Studio Code 홈페이지에서 PHP 프로그래밍을 하는 방법에 대하여 소개되어 있는 페이지가 있습니다. 아래 링크를 클릭해 주세요.

https://code.visualstudio.com/docs/languages/php


이 페이지대로만 하면 쉽게 할 수 있겠다고 생각하겠지만 그렇지 않습니다.


전제 조건으로 PHP가 컴퓨터에 설치되어 있어야 합니다.


1. http 서버 및 php 설치


    - http 서버는 apache를 사용해도 되고 윈도우에서 제공하는 iis를 중 원하는 서버를 설치 및 설정합니다.

    - php는 홈페이지에서 직접 다운로드 받아서 설치합니다. iis의 경우 "웹 플랫폼 설치 관리자"를 통해 php를 설치할 수도 있습니다.


2. PHP 확장프로그램 설치


    - 서버 설정 및 php 설치가 완료되었으면 visual studio code 확장 프로그램 중 PHP IntelliSense 와 PHP Debug 를 설치합니다.


3. php 실행파일 경로 설정


    - 설치가 완료되었으면 상단 메뉴 중 파일(F) - 기본 설정(P) - 설정(S) 로 들어가서 php 실행파일 경로를 지정합니다.


4. 디버깅


    - 디버깅을 위해서는 xdebug 를 설치해야 합니다. (저는 여기서 막혀서 좀 해맸습니다.)

    4-1, xdebug 설치 방법

        - 가장 쉽게 xdebug를 설치하는 방법은 xdebug install wizard 페이지(https://xdebug.org/wizard.php)에 phpinfo의 정보를 복사해서 붙여넣기 하면 설치 방법을 알려줍니다.

        4-1-1) xdebug 파일(dll 파일 1개)을 다운로드 받습니다.

        4-1-2) php설치폴더 하위에 있는 ext" 폴더에 다운로드 받은 dll 파일을 복사합니다.

        4-1-3) php설치폴더에 있는 php.ini 파일을 편집기로 열어서 xdebug 관련 설정 값을 추가합니다.


[XDebug]

zend_extension="xdebug dll 파일이 있는 경로"

xdebug.remote_enable = 1

xdebug.remote_autostart = 1


        4-1-4) 웹 서버를 재시작 합니다.

    

    - xdebug 설치가 완료된 후에 visual studio code 를 재시작합니다.

    - php 폴더를 추가하고 php 파일을 열고 F5 버튼을 클릭하면 디버그 언어를 선택하는 창이 나타납니다(java php 등)

    - php를 선택하면 xdebug를 활용하여 디버깅을 할 수 있습니다.


감사합니다.

+ Recent posts