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

감사합니다.

몇 년동안 블로그 관리를 안 하다 보니 구글 애드센스가 제대로 동작하지 않아서 방법을 찾아보다가 잘 운영되고 있는 티스토리에서 사용하고 있는 반응형 스킨을 발견하고 저도 설치하기로 했습니다. 스킨 명은 FastBoot 입니다.

아래 링크를 클릭해서 들어가서 파일 다운로드 및 스킨 등록 및 설정을 해주시면 됩니다.
http://blog.readiz.com/214

아래쪽으로 내려가다 보면 다운로드 부분에서 최신 버전을 다운로드 받으면 됩니다.
현재 V1.6.2 가 최신버전이고 2 버전 개발중이십니다. 기다리고 있겠습니다.

기본 설치 방법은 아래 링크를 확인해 주세요.

http://blog.readiz.com/152

위 글의 내용을 요약하면 다음과 같습니다.

1. 다운로드 받은 zip 파일 압축을 풉니다.

2. 관리자모드로 로그인 후 왼쪽 메뉴의 꾸미기 - 스킨변경을 클릭합니다. 그리고 오른쪽 상단에 있는 "스킨등록+" 버튼을 클릭합니다.

3. 오른쪽 상단에 있는 추가 버튼을 클릭하여 압축 푼 파일을 모두 업로드 합니다.(루트폴더 업로드, images 폴더 업로드, 총 2회)

4. 오른쪽 하단의 저장 버튼을 클릭하고 스킨명을 "FastBoot v1.6.2" 로 지정합니다.

5. 다시 왼쪽 메뉴의 꾸미기 - 스킨변경을 클릭하고, 스킨 목록 오른쪽 아래에 있는 스키보관함을 클릭하면 방금 올린 "FastBoot v1.6.2" 스킨 하나가 나타납니다. 해당 스킨을 클릭 후에 적용 버튼을 클릭하면 "FastBoot v1.6.2" 스킨이 적용됩니다.

6. 반응형 홈페이지기 때문에 모바일웹을 OFF 시켜 줍니다.

7. 기타 원하는데로 설정을 바꿔줍니다.
http://blog.readiz.com/214 글 추가설정 부분 참고

현재 블로그가 FastBoot v1.6.2 스킨을 적용하였습니다.
다만 홈 화면에서도 사이드바가 나오게 하고 싶은데 어떻게 하는지 모르겠네요...ㅜㅜ

(아시는 분 댓글이나 연락 주셔서 도와주시면 정말 감사하겠습니다.)

그리고 구글 애드센스는 기존 계정을 탈퇴하고 바로 다시 신청하였습니다. 
최대 1일정도 걸린다고 하니 내일 쯤 애드센스가 제대로 동작하는지 알아봐야겠네요.
(2017년 5월 27일)

신청 결과 아직 부족한 내용이 있어서 승인되지 못했습니다.
좀더 많은 내용을 올린 후에 다시 신청하겠습니다.

감사합니다.

'유용한 정보 > 프로그램' 카테고리의 다른 글

Youtube 영상 다운로드 프로그램  (0) 2018.06.07
SyntaxHighlighter 사용하기  (0) 2018.06.04

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

윈도우에서 파일의 정보를 가져오기 위해서 기본적으로 사용하고 있는 클래스는 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 보다 많은 것을 확인할 수 있습니다. 이 부분에 대해 아시는 분 있으면 댓글 남겨주세요. 저도 관련 정보를 더 찾아보도록 하겠습니다.

감사합니다.

+ Recent posts