안드로이드에서는 ImageView 사용하여 이미지 리소스를 보여줄 수 있다. 여기서 Drawable이나 Bitmap을 사용하여서 이미지 크기를 조절할 수도 있다.

 

 

 

- 밀도에 따른 Drawable 파일 만들기

밀도 : 안드로이드는 각종 기기에 사용하므로, 화면 크기에 따라 밀도가 달라진다.

 

그래서 밀도에 따른 이미지를 구분하여 파일을 만든 후 이미지 리소스를 넣는다면 이보다 작은 밀도를 가진 기기에서는 이미지가 축소되고, 큰 기기에서는 확대되어서 보이게 된다.

 

 

밀도 단위 메뉴(홈) 아이콘  액션바/상태바 아이콘 
mdpi 1px(픽셀) = 1dp 48 x 48 px 24 x 24 px
hdpi 1.5px(픽셀) = 1dp  72 x 72 px  36 x 36 px 
xhdpi 2px(픽셀) = 1dp 96 x 96 px 48 x 48 px 
xxhdpi 3px(픽셀) = 1dp  144 x 144 px  72 x 72 px 
xxxhdpi 4px(픽셀) = 1dp 192 x 192 px 96 x 96 px 

( ※ dp = dpi/160, 기기마다 해상도의 크기가 다르므로 단위로 dp를 사용해야 동일하게 보인다. )

 

 

 

▲ 1. res 디렉터리에서 [New] -> [Android Resource Directory] 클릭

 

 

 

 

 

▲ 2. Resource type을 drawable로 선택 후 목록에서 Desity(밀도)를 선택한 후 >> 버튼을 클릭

 

 

 

 

 

▲ 3. 밀도를 선택한다. 현재 나오는 기기들의 밀도를 생각하여 선택해준다.

 

 

 

 

 

▲ 4. 이제 추가 할 이미지를 복사 후 drawable 디렉터리를 선택한 후 붙여넣기 한다.

 

 

 

 

 

▲ 5. 그러면 추가한 xhdpi 디렉터리를 확인할 수 있고, 이 디렉터리로 이미지 리소스를 넣어주면 된다.

 

 

안드로이드 스튜디오 자동 import 설정하기

 

 

 

 

 1. [File] -> [Settings...] 으로 간다.

 

 

 

 

 

 

 2. [Editor] -> [General] -> [Auto import] 로 간다.   (or 검색창의 Auto import를 검색)

 

 

 

 

 

 

 3. 각 XML 이나 Java에서 자동으로 improt 될 필요가 있다고 생각하는 부분을 체크해준 후 OK 해준다.

 

 

 

 

 

+)

자동으로 import 되기 때문에 최종적으로 작업이 끝났을 경우 사용하지 않는 것들이 import 되어있을 경우가 많다. 

 

import문들을 보면 사용하지 않는 것은 회색으로 처리되어 있으니, 작업이 끝난 후 최종적으로 한 번 import문들을 정리해 주는 것이 좋다.

안드로이드 코드 난독화

 

컴파일된 자바 파일을 디컴파일하면 코드가 노출된다. 디컴파일이란 간단히 말하여 컴파일의 반대 과정이다.

 

 

이러한 디컴파일로 인하여 코드의 노출을 방지하기 위해서 디컴파일해도 코드를 읽기 어렵게 만들기 위한 일종의 코드 보안 기술이다.

 

 

그래서 앱 출시 전 난독화를 하는 것이 좋은데 이는 안드로이드 스튜디오에서 기본적으로 지원하는 난독화 프로그램 프로가드(Proguard) 사용할 수 있다.

 

 

 

 

 

 

 

▲ 1. 모듈 수준의 그레이들 파일을 열어준다.

 

 

 

 

▲ 2. mainfyEnabled의 값으로 true를 준다.

 

 

 

 

 

 3. Sync Now를 클릭한다.

 

 

 

이것으로 코드의 난독화를 하게 된다.

 

 

 

 

 

 

+)

 안드로이드에서는 debug 빌드와 release 빌드를 할 수 있다.

 

debug 빌드 : 코딩 중 <Run>(▶) 버튼으로 연결된 기기나 에뮬레이터로 실행하였을 경우

 

release 빌드 : 작업이 끝나 최종적으로. apk 파일을 만들 경우

 

기본적으로는 release 부분만이 선언되어있지만 이를 복사하여서 dubug문을 만들면 debug 빌드 시에도 코드 난독화가 일어나게 할 수 있다.

 

 

 

1. 문제

 

사람과 컴퓨터의 가위바위보 대결

 

사람과 컴퓨터가 가위바위보 게임을 하는 프로그램을 작성하라. 선수 이름은 프로그램 실행 초기에 키 입력받는다. 컴퓨터가 무엇을 낼지는 독자가 마음대로 프로그래밍하면 된다. 저자는 컴퓨터가 랜덤하게 내도록 코딩하였다. 사람이 키보드로부터 입력받고 <Enter> 키를 치면 곧바로 결과가 나온다. 가위, 바위, 보가 아닌 다른 문자를 입력하면 다시 입력받는다.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;

class AbstractPlayer {
	string name;
protected:
	string gbb[3];
public:
	AbstractPlayer(string name) {
		this->name = name;
		gbb[0] = "가위"; gbb[1] = "바위"; gbb[2] = "보";
	}
	virtual string turn() = 0;
	string getName() { return name; }
};

class Human : public AbstractPlayer {
public:
	Human(string name) : AbstractPlayer(name) { ; }
	string turn() {
		string gg;
		while (1) {
			cout << getName() << ">>";
			getline(cin, gg);
			if (gg == "가위" || gg == "바위" || gg == "보")
				return gg;
		}
	}
};

class Computer : public AbstractPlayer {
public:
	Computer() : AbstractPlayer("Computer") {
		srand((unsigned)time(0));
	}
	string turn() {
		int num = rand() % 3;
		return gbb[num];
	}
};

int main() {
	string name;

	cout << "***** 컴퓨터와 사람이 가위 바위 보 대결을 펼칩니다. *****" << endl;
	cout << "선수 이름을 입력하세요>>";
	getline(cin, name);

	Human h(name);
	Computer c;

	while (1) {
		string temp = h.turn();
		string com = c.turn();
		cout << c.getName() << ": " << com << endl;
		if (temp == com)
			cout << "the same" << endl;
		else if (temp == "바위") {
			if (com == "가위")
				cout << h.getName() << " is winner." << endl;
			else
				cout << c.getName() << " is winner." << endl;
		}
		else if (temp == "가위") {
			if (com == "보")
				cout << h.getName() << " is winner." << endl;
			else
				cout << c.getName() << " is winner." << endl;
		}
		else if (temp == "보") {
			if (com == "바위")
				cout << h.getName() << " is winner." << endl;
			else
				cout << c.getName() << " is winner." << endl;
		}
	}
}

 

 

4. 설명

 

컴퓨터일 경우 turn함수에서 가위, 바위, 보 중 랜덤한 것을 출력하도록 하였고

 

사람일 경우 값을 입력받아 가위, 바위, 보 중 하나가 아니면 무시하고 다시 한번 더 입력을 받고 이 중 하나라면 그 값을 저장, 컴퓨터와 비교하도록 하였다.

 

1. 문제

 

14. vector<Shape*> v;를 이용하여 간단한 그래픽 편집기를 콘솔 바탕으로 만들어보자. Shape과 Circle, Line, Rect 클래스는 다음과 같다. 생성된 도형 객체를 v에 삽입하고 관리하라. 9장 실습 문제 10번의 힌트를 참고하라.

 

그래픽 편집기의 기능은 "삽입", "삭제", "모두보기", "종료"의 4가지이고, 실행 과정은 다음과 같다.

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Shape {
protected:
	virtual void draw() = 0;
public:
	void paint() { draw(); }
};

class Circle : public Shape {
protected:
	virtual void draw() { cout << "Circle" << endl; }
};
class Rect : public Shape {
protected:
	virtual void draw() { cout << "Rectangle" << endl; }
};
class Line : public Shape {
protected:
	virtual void draw() { cout << "Line" << endl; }
};

class UI {
public:
	static int main_memu() {
		int n;
		cout << "삽입:1, 삭제:2, 모두보기:3, 종료:4 >> ";
		cin >> n;
		return n;
	}
	static int one_menu() {
		int n;
		cout << "선:1, 원:2, 사각형:3 >> ";
		cin >> n;
		return n;
	}
	static int two_menu() {
		int n;
		cout << "삭제하고자 하는 도형의 인덱스 >> ";
		cin >> n;
		return n;
	}
};

class GraphicEditor {
	vector<Shape*> v;
	vector<Shape*>::iterator it;

public:
	GraphicEditor() { ; }
	void create(int num) {
		switch (num) {
		case 1:
			v.push_back(new Line());
			break;

		case 2:
			v.push_back(new Circle());
			break;

		case 3:
			v.push_back(new Rect());
			break;
		}
	}
	void indelete(int num) {
		Shape *del;

		if (num < v.size()) {
			it = v.begin();
			for (int i = 0; i< num; i++)
				it++;
			del = *it;
			it = v.erase(it);
			delete del;
		}
		else
			cout << "인덱스를 잘못 입력하셨습니다." << endl;
	}
	void call() {
		bool exit = true;
		cout << "그래픽 에디터입니다." << endl;
		while (exit) {
			switch (UI::main_memu()) {
			case 1:
				create(UI::one_menu());
				break;
			case 2:
				indelete(UI::two_menu());
				break;
			case 3:
				for (int i = 0; i< v.size(); i++) {
					cout << i << ": ";
					v[i]->paint();
				}
				break;
			case 4:
				exit = false;
				break;
			}
		}
	}
};

int main() {
	GraphicEditor* editor = new GraphicEditor;
	editor->call();
	delete editor;
}

 

4. 설명

 

파일은 따로 분리하지 않았습니다.

 

9장 10번과

10장 13번 문제를 이해하셨다면 어려움 없이 풀 수 있는 문제였습니다.

 

1. 문제

 

13. vector를 이용하여 아래 Circle 클래스의 객체를 삽입하고 삭제하는 프로그램을 작성하라. 삭제 시에는 이름이 같은 모든 원을 삭제한다.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Circle {
	string name;
	int radius;
public:
	Circle(int radius, string name) {
		this->radius = radius; this->name = name;
	}
	double getArea() { return 3.14*radius*radius; }
	string getName() { return name; }
};

int main() {
	vector<Circle*> v;
	vector<Circle*>::iterator it;

	int num, radius;
	string name;
	bool exit = true;

	cout << "원을 삽입하고 삭제하는 프로그램입니다." << endl;
	while (exit) {
		cout << "삽입:1, 삭제:2, 모두보기:3, 종료:4 >> ";
		cin >> num;
		//fflush(stdin);
		while(getchar() != '\n');
		switch (num) {
		case 1:
			cout << "생성하고자 하는 원의 반지름과 이름은 >> ";
			cin >> radius >> name;
			v.push_back(new Circle(radius, name));
			break;
		case 2:
			cout << "삭제하고자 하는 원의 이름은 >> ";
			getline(cin, name);
			it = v.begin();
			while (it != v.end()) {
				Circle *c = *it;
				if (c->getName() == name) {
					it = v.erase(it);
					delete c;
				}
				else
					it++;
			}
			break;
		case 3:
			for (it = v.begin(); it != v.end(); it++)
				cout << (*it)->getName() << endl;
			cout << endl;
			break;
		case 4:
			exit = false;
			break;
		}
	}

}

 

4. 설명

 

vector<Circle*> v;

 

vector<Circle*>::iterator it;

 

로 2개의 변수를 생성합니다.

 

힌트를 보시면 이해하시는데 큰 어려움은 없으실 겁니다.

 

1. 문제

 

12. Open Challenge를 수정하여 사용자가 어휘를 삽입할 수 있도록 기능을 추가하라.

실행 예는 다음과 같다.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;

class Word {
	string en;
	string ko;
public:
	Word() { en = ""; ko = ""; }
	Word(string en, string ko) {
		this->en = en; this->ko = ko;
	}
	void setEnKo(string en, string ko) { this->en = en; this->ko = ko; }
	string getEn() { return en; }
	string getKo() { return ko; }
};

int main() {

	vector<Word> v;
	Word w;
	v.push_back(Word("human", "인간"));
	v.push_back(Word("society", "사회"));
	v.push_back(Word("dall", "인형"));
	v.push_back(Word("emotion", "감정"));
	v.push_back(Word("painting", "그림"));
	v.push_back(Word("trade", "거래"));
	v.push_back(Word("animal", "동물"));
	v.push_back(Word("photo", "사진"));
	v.push_back(Word("bear", "곰"));

	srand((unsigned)time(0));
	int n1; string answer;
	string bogi[4]; for (int i = 0; i<4; i++) bogi[i] = "";
	int number[4]; for (int i = 0; i<4; i++) number[i] = 0;
	int i;
	bool exit = true, exit2 = true;
	int sel;
	string e, k;

	cout << "***** 영어 어휘 테스트를 시작합니다. *****" << endl;

	while (exit2) {
		exit = true;
		cout << "어휘 삽입: 1, 어휘 테스트 : 2, 프로그램 종료:그외키 >> ";
		cin >> sel;
		switch (sel) {
		case 1:
			cout << "영어 단어에 exit을 입력하면 입력 끝" << endl;
			//fflush(stdin);
			while (getchar() != '\n');
			while (1) {
				cout << "영어 >>";  getline(cin, e);
				if (e == "exit") break;
				cout << "한글 >>";  getline(cin, k);
				w.setEnKo(e, k);
				v.push_back(w);
			}
			break;
		case 2:
			cout << "영어 어휘 테스트를 시작합니다. 1~4 외 다른 입력시 종료합니다." << endl;
			while (exit) {
				n1 = rand() % v.size();
				bogi[0] = v.at(n1).getKo();
				answer = bogi[0];
				cout << v.at(n1).getEn() << "?" << endl;

				while (exit) {				// 중복되지 않는 보기 만들기
					for (i = 1; i<4; i++) {
						n1 = rand() % v.size();
						bogi[i] = v.at(n1).getKo();
					}
					if (bogi[0] != bogi[1] && bogi[0] != bogi[2] && bogi[0] != bogi[3] &&
						bogi[1] != bogi[2] && bogi[1] != bogi[3] && bogi[2] != bogi[3])
						exit = false;
				}
				exit = true;

				number[0] = rand() % 4;
				while (exit) {					//보기 순서 섞기
					for (i = 1; i<4; i++) {
						number[i] = rand() % 4;
					}
					if (number[0] != number[1] && number[0] != number[2] && number[0] != number[3] &&
						number[1] != number[2] && number[1] != number[3] && number[2] != number[3])
						exit = false;
				}
				exit = true;
				int result;

				for (i = 1; i<5; i++)
					cout << "(" << i << ") " << bogi[number[i - 1]] << " ";
				cout << ":>";
				cin >> result;

				if (result != 1 && result != 2 && result != 3 && result != 4)	//순서 중요 먼저 1, 2, 3, 4 이외의 값인지 확인해야함
					exit = false;
				else if (answer == bogi[number[result - 1]])
					cout << "Excellent !!" << endl;
				else if (result == 1 || result == 2 || result == 3 || result == 4)
					cout << "No. !!" << endl;
			}
			break;
		default:
			exit2 = false;
			break;
		}
		cout << endl;
	}
}

 

 

4. 설명

 

주의 하실점이라면 퀴즈를 푼 후 어휘를 삽입할려고 할 시 먼저 입력 버퍼를 비워준 후 단어를 입력 받아야 합니다.

 

전글에서 이야기 했듯이 while( getchar() != '\n');을 이용하여서 입력버퍼를 비워 줍니다.

 

대부분 앞의 문제들에서 사용하였던 것이고, 주석으로 무엇을 구현한 것인지 간략히 구분해 놨으므로 이해하시는데는 큰 문제 없으실겁니다.

 

1. 문제

 

11. 책의 년도, 책이름, 저자 이름을 담은 Book 클래스를 만들고, vector<Book> v;로 생성한 벡터를 이용하여 책을 입고하고, 저자와 년도로 검색하는 프로그램을 작성하라.

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Book {
	int year;
	string name;
	string writer;
public:
	void setInfo(int ye, string na, string wr) {
		year = ye;
		name = na;
		writer = wr;
	}
	int getYear() { return year; }
	string getWriter() { return writer; }
	void search() { cout << year << "년도, " << name << ", " << writer << endl; }
};

int main() {

	vector<Book> v;
	Book b;
	int year; string name, writer;

	cout << "입고할 책을 입력하세요. 년도에 -1를 입력하면 입고를 종료합니다." << endl;
	while (1) {
		
		cout << "년도>>"; cin >> year;
		if (year == -1) break;
		//fflush(stdin);
		while (getchar() != '\n');

		cout << "책이름>>"; getline(cin, name);
		cout << "저자>>"; getline(cin, writer);

		b.setInfo(year, name, writer);
		v.push_back(b);
	}
	int num = v.size();
	cout << "총 입고된 책은 " << num << "권입니다." << endl;
	cout << "검색하고자 하는 저자 이름을 입력하세요>>";
	//fflush(stdin);
	while (getchar() != '\n');
	getline(cin, writer);

	for (int i = 0; i< num; i++)
		if (v[i].getWriter() == writer) v[i].search();

	cout << "검색하고자 하는 년도를 입력하세요>>";
	cin >> year;

	for (int i = 0; i< num; i++)
		if (v[i].getYear() == year) v[i].search();
}

 

4. 설명

 

 

fflush(stdin)으로 버퍼를 비워주는 것이 visual studio 2017에서 먹히지 않아서 달리 버퍼를 지워주는 while( getchar() != '\n' ); 을 삽입해 주었습니다.

 

 

아마 2015년 버전 이후부터 보안상으로 막아 논 것 같습니다.

 

+ Recent posts