티스토리 뷰
[Android] 안드로이드 빌드 시 리소스 자동화(android build automated resources)
Bㅇㅇker 2017. 12. 18. 09:48이 포스팅은 tiii님의 포스팅(http://tiii.tistory.com/22)을 기반으로 작성하였습니다.
제가 직접 돌리면서 부족한 부분과 어려웠던 부분을 나누고자 합니다.
설치 및 시나리오는 참고 사이트를 확인해주세요.
1. 파이썬 설치
https://www.python.org/ftp/python/2.7.11/python-2.7.11.msi
2. 환경변수에 파이썬 Path 추가 (C:\Python27)
* 윈도우 기준
3. 파이썬에 setuptools, pip, gdata 설치
Setuptools :
- https://pypi.python.org/pypi/setuptools/1.0
- (또는) https://www.versioneye.com/python/setuptools/1.0
1) 위의 사이트에서 다운로드
2) cmd 창에서 다운 받은 폴더로 이동
3) python ez_setup.py build 입력 후 python ez_setup.py
4. 환경변수에 파이썬 script Path 추가
(C:\Python27\Scripts)
5. Pip설치
1) cmd 창에서 3번에서 다운로드한 setuptool에 이동
2) easy_install pip 입력 (bestest 7.1.2)
6. gdata 설치
1) cmd 창에서 3번에서 다운로드한 setuptool에 이동
2) easy_install gdata 입력 (latest 2.0.18)
7. AndroidStudio에 Python Community Edition Plugin 설치
포스팅에서는 Python Community Edition Plugin 이 있다고 나오지만 제가 테스트할 때는 찾아볼 수 없었습니다.
그대신 Python 이라는 것으로 있어서 이것으로 테스트하였습니다. (통합된 것을 예상됩니다.)
[포스팅에서 언급한 Python Community Edition]
[테스트한 Python Plugin]
8. 프로젝트에 파이썬 스크립트 복사
아이디와 패스를 넣었더니 권한 없음 오류를 뿜어내서 소스를 수정하여 아이디와 password를 받지 않고 링크가 있는 읽기전용 파일을 받아오도록 하였습니다.
경로는 [module name] - script가 Default 입니다만 소스를 수정하여 변경 할 수 있습니다.
포스트에서 언급한 경로로 이동하는 가장 쉬운 방법은 3단계로 구성됩니다.
1) app > 마우스 오른쪽 단추 > Show in Explorer
2) window 창 호출 되면 app 폴더 진입
3) script 폴더 생성
위의 방법으로 하면 script 폴더가 생성된 것을 확인할 수 있습니다. 이 폴더안에 아래의 파이썬 스크립트 복사해주세요.
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import csv;
import gdata.docs.service
import gdata.spreadsheet.service
from xml.etree.ElementTree import ElementTree, Element, SubElement, dump
'''
get google doc information from the command line argument
download method
Create by : YoungChan Lee
Modify by : KyuChan Shin
'''
def get_gdoc_information_android():
#email = raw_input('Email address:')
#password = getpass('Password:')
#gdoc_id = raw_input('Google Doc Id:')
gdoc_id = sys.argv[1]
downloadpath = sys.argv[2]
try:
file_path = download(gdoc_id)
readCSV(downloadpath,file_path)
except Exception, e:
print ":::::::::::::ERROR:::::::::::::"
print(e)
#raise e
def download(gdoc_id, download_path=None, ):
print "Downloading the CVS file with id %s" % gdoc_id
gd_client = gdata.docs.service.DocsService()
#auth using ClientLogin
gs_client = gdata.spreadsheet.service.SpreadsheetsService()
#gs_client.ClientLogin(email, password)
#getting the key(resource id and tab id from the ID)
resource = gdoc_id.split('#')[0]
tab = gdoc_id.split('#')[1].split('=')[1]
resource_id = 'spreadsheet:'+resource
if download_path is None:
download_path = os.path.abspath(os.path.dirname(__file__))
file_name = os.path.join(download_path, '%s.csv' % (gdoc_id))
print 'download_path : %s' % download_path;
print 'Downloading spreadsheet to %s' % file_name
docs_token = gd_client.GetClientLoginToken()
gd_client.SetClientLoginToken(gs_client.GetClientLoginToken())
gd_client.Export(resource_id, file_name, gid=tab)
gd_client.SetClientLoginToken(docs_token)
print "Download Completed!"
return file_name
def readCSV(savepath, file_name):
print "read CSV file : %s" % file_name
SourceCSV= open(file_name,"r")
csvReader = csv.reader(SourceCSV)
header = csvReader.next()
androidkey_idx = header.index("android_key")
eng_idx = header.index("eng")
kor_idx = header.index("kor")
# Make an empty Element
resources_eng = Element("resources")
resources_kor = Element("resources")
# Loop through the lines in the file and get each coordinate
for row in csvReader:
androidkey = row[androidkey_idx]
eng = row[eng_idx]
kor = row[kor_idx]
if not row[kor_idx]:
kor = row[eng_idx]
#append eng resource
if row[eng_idx]:
string_eng = Element("string")
string_eng.attrib["name"] = androidkey.decode('utf-8')
string_eng.text = eng.decode('utf-8')
resources_eng.append(string_eng)
#append kor resource
string_kor = Element("string")
string_kor.attrib["name"] = androidkey.decode('utf-8')
string_kor.text = kor.decode('utf-8')
resources_kor.append(string_kor)
# Print the coordinate list
#dump(resources_eng)
#dump(resources_kor)
#Make Resource Folder
newpath_en = savepath+r'\values'
if not os.path.exists(newpath_en):
os.makedirs(newpath_en)
newpath_ko = savepath+r'\values-ko'
if not os.path.exists(newpath_ko):
os.makedirs(newpath_ko)
#make Xml file
ElementTree(resources_eng).write(newpath_en+"\\string.xml", "utf-8")
ElementTree(resources_kor).write(newpath_ko+"\\string.xml", "utf-8")
SourceCSV.close()
os.remove(file_name)
if __name__=='__main__':
get_gdoc_information_android()
IOS 같은 경우는 포스트 한 곳에서 김로또님께서 재능기부해주셨습니다.
readCSV 쪽 함수만 수정해서 사용했다고 합니다.
https://slack-files.com/T02TMQL6T-F1JPBNSP3-986c3e480d
def readCSV(savepath, file_name):
# print "read CSV file : %s" % file_name
SourceCSV = open(file_name,"r")
csvReader = csv.reader(SourceCSV)
header = csvReader.next()
languages = ["ko", "en"]
indexes = [0, 0]
values = ["", ""]
keyIndex = header.index("key")
for i, language in enumerate(languages):
indexes[i] = header.index(language)
for row in csvReader:
for i, language in enumerate(languages):
key = '"' + row[keyIndex] + '"'
value = '"' + row[indexes[i]] + '"'
values[i] = values[i] + key + "=" + value + ";\n"
for i, language in enumerate(languages):
outputFile = savepath + "/" + language + ".lproj/Localizable.strings"
try:
outputStream = open(outputFile, "w")
outputStream.write(values[i])
outputStream.close()
except :
print "Error: " + language
SourceCSV.close()
os.remove(file_name)
9.구글 시트 만들기
구글 닥스에서 스프레드 시트를 생성합니다.
구글 시트는 메인개발자(관리자)와 번역가를 이메일로 초대하여 수정권한을 제한합니다.
시트 구조는 위와 같이 영어, 한국어, ios, android 구분하여서 등록합니다.
만약 더 많은 언어를 지원할 경우 eng, kor, 기타 나라, ios, android 순으로 설정하는게
나중에 소스 편집하는데 더 편할 것으로 예상됩니다.
10.구글 스크립트 생성
function myFunction() {
}
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "iOS Resource sheet",
functionName : "iOSSheet"
}, {
name : "Android Resource sheet",
functionName : "AndroidSheet"
}];
sheet.addMenu("리소스 만들기", entries);
};
function AndroidSheet(){
var FileName = SpreadsheetApp.getActiveSpreadsheet().getName()+"_and";
var files = DriveApp.getFilesByName(FileName);
var sheet;
// Check we found a sheet with the name
while (files.hasNext()){
sheet = files.next();
if(sheet.getName() == FileName){
Logger.log("Opened Sheet: " + FileName);
return makeAndroidResource(sheet.getId());
}
}
// We didn't find the file, so create it.
sheet = SpreadsheetApp.create(FileName);
Logger.log("Created new Sheet for: " + FileName);
return makeAndroidResource(sheet.getId());
}
function iOSSheet(){
var FileName = SpreadsheetApp.getActiveSpreadsheet().getName()+"_iOS";
var files = DriveApp.getFilesByName(FileName);
var sheet;
// Check we found a sheet with the name
while (files.hasNext()){
sheet = files.next();
if(sheet.getName() == FileName){
Logger.log("Opened Sheet: " + FileName);
return makeiOSResource(sheet.getId());
}
}
// We didn't find the file, so create it.
sheet = SpreadsheetApp.create(FileName);
Logger.log("Created new Sheet for: " + FileName);
return makeiOSResource(sheet.getId());
}
function makeAndroidResource(fileId){
// Get Spreadsheets
var SourceSpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var Targetspreadsheet = SpreadsheetApp.openById(fileId); //새로운 파일
// Set Sheets
var SourceSheet = SourceSpreadSheet.getSheets()[0];
var TargetSheet = Targetspreadsheet.getSheets()[0];
TargetSheet.clear();
// Get Source last row
var last_row = SourceSpreadSheet.getLastRow();
// Set Ranges
var source_range = SourceSpreadSheet.getRange("A1:C"+last_row);
var target_range = Targetspreadsheet.getRange("A1:C"+last_row);
// 안드로이드 키 값
var source_key_range = SourceSpreadSheet.getRange("D1:D"+last_row);
var target_key_range = Targetspreadsheet.getRange("C1:C"+last_row);
// Fetch values
var values = source_range.getValues();
var key_values = source_key_range.getValues();
// Save to spreadsheet
target_range.setValues(values);
target_key_range.setValues(key_values);
}
function makeiOSResource(fileId){
// Get Spreadsheets
var SourceSpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var Targetspreadsheet = SpreadsheetApp.openById(fileId); //새로운 파일
// Set Sheets
var SourceSheet = SourceSpreadSheet.getSheets()[0];
var TargetSheet = Targetspreadsheet.getSheets()[0];
TargetSheet.clear();
// Get Source last row
var last_row = SourceSpreadSheet.getLastRow();
// Set Ranges
var source_range = SourceSpreadSheet.getRange("A1:C"+last_row);
var target_range = Targetspreadsheet.getRange("A1:C"+last_row);
// ios 키 값
var source_key_range = SourceSpreadSheet.getRange("C1:C"+last_row);
var target_key_range = Targetspreadsheet.getRange("C1:C"+last_row);
// Fetch values
var values = source_range.getValues();
var key_values = source_key_range.getValues();
//ignore header
for(var i=1; i< values.length; i++){
values[i][0] = "\""+key_values[i]+"\"=\""+ values[i][0] +"\";";
values[i][1] = "\""+key_values[i]+"\"=\""+ values[i][1] +"\";";
values[i][2] = "\""+key_values[i]+"\"=\""+ values[i][2] +"\";";
}
// Save to spreadsheet
target_range.setValues(values);
//target_key_range.setValues(key_values);
}
위의 내용을 리소스 편집기에 넣어둡니다.
시트로 돌아가면 "리소스 만들기" 메뉴가 생성되어 있습니다.
이 새로 생성된 메뉴를 이용하여 안드로이드, ios 용 시트를 생성합니다.
생성된 시트로 이동하여서 공유하기를 누릅니다.
인터넷의 모든 사용자가 찾고 볼 수 있음을 클릭합니다.
이 부분이 가장 중요합니다. 전 이 권한을 잘못 설정해서 몇 시간 고생했습니다 ㅠ
11. build.gradle 수정하기
build.gradle에 파이선 스크립트를 실행하는 task를 추가합니다.
ext.download_res_folder = 'src/main/res_down' //저장될 별도의 리소스 폴더
ext.script_path = 'script/languageResource.py' //스크립트 저장 경로
ext.GoogleDocId = 'Google Doc ID'
task StringResourceSync(type: Exec) {
doFirst {
println ":::" + "Start to get String Resources..." + ":::"
}
commandLine = ['cmd', '/c', 'python' , script_path, GoogleDocId,download_res_folder]
//mac
//commandLine =['python', script_path, GoogleDocId,download_res_folder]
doLast {
println ":::" + "Finish to get String Resources..." + ":::"
}
}
preBuild.dependsOn StringResourceSync
android {
...
sourceSets {
main.res.srcDirs += download_res_folder
}
...
}
12.gradle sync
프로젝트를 빌드하거나 gradle 프로젝트를 project sync 하게 되면 언어 리소스를 다운받아 새로운 언어 리소스를 생성합니다.
자세한 설명과 소스는 http://tiii.tistory.com/22 을 참고해주세요.
정리
파이션을 응용해서 gradle을 사용하면 더 다양한 안드로이드 빌드가 가능 할 것으로 보입니다.
참고
* http://tiii.tistory.com/22
* https://www.versioneye.com/python/setuptools/1.0
'프로그래밍 > Android' 카테고리의 다른 글
[Android] Full Screen 모드 전환 (0) | 2017.12.18 |
---|---|
[Android] [버그이슈] 앱 빌드 시도 시 아무런 동작 안하는 이슈 (0) | 2017.12.18 |
[Android] 해상도에 따른 UI 구성에 필요한 도구 (0) | 2017.12.18 |
[Android] 화면 회전 상태 확인 방법 (0) | 2017.12.18 |
[Android] 회전 ViewPager (Carousel ViewPager) (5) | 2017.12.18 |
- 탁구
- IOS
- 점수판
- 고시문
- 스코어헬퍼
- java
- view
- Kotlin
- IT
- 알고리즘
- RXjava
- MCC
- DI
- 미션차이나센터
- 패턴
- push
- 코틀린
- missioon
- swift
- 디자인패턴
- missionchina
- 선교
- Android
- issue
- Android Studio
- flutter
- 임용고시
- 안드로이드
- 고시문헬퍼
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |