고수 개발자가 아닌 일반 유저가 할 수 있는 이미지 파일 교체, 수정을 제외한 트윅 작업의 대부분은 sxml, smali 등의 텍스트 파일 수정입니다.
물론 수작업으로 하면 되는데 이걸 쉽게 반복할 수 있는 방법이 스크립트를 이용하는 것이지요.
제가 스크립트에 관심을 가지게 된 것도 이런 이유입니다.
feature.xml 을 수정만 하면 카메라 무음이 되던 시절입니다.
루익으로 파일을 열어서 라인을 찾고 true 로 바꾸었지요.
펌업이 있으면 매번 반복하는게 싫어서 구글링했던 정리해봅니다.
비지박스 명령 중에 sed 는 텍스트 파일을 수정, 삭제, 첨가 하는 기능이 있습니다.
#shutter sound menu
sed -i '/ShutterSoundMenu/s/false/true/g' /system/csc/feature.xml
-- 요 구문은 xml 파일에서 ShutterSoundMenu 라는 문구가 들어간 라인을 찾아서
s = substitute 대체 하라는 명령입니다. false 가 true 로 바뀌는 거지요.
-i 옵션은 대상 xml 파일을 직접 수정하는 옵션입니다.
#browser close menu
sed -i '/WEB/a<CscFeature_Web_AddOptionToTerminate>true</CscFeature_Web_AddOptionToTerminate>' /system/csc/feature.xml
sed -i '/WEB/a<CscFeature_Web_TerminateAppOnCloseAllAction>true</CscFeature_Web_TerminateAppOnCloseAllAction>' /system/csc/feature.xml
-- 요 구문은 없는 라인을 추가하는 명령입니다. WEB 이라는 단어가 들어간 라인 뒤에 a = add 하는 거지요. 그러니 이 명령은 false true 가 들어있지 않고 넣으려는 라인의 텍스트가 존재하는겁니다.
지우는 d delete 명령 옵션도 있으나 유저 입장에서 크게 쓰지 않는 기능입니다.
자 이번엔 텍스트 파일 중에서 일부분만 뽑아내는 기능에 관한 설명입니다.
head, tail, awk 등으로 가능합니다.
head -n 4 text.txt | tail -n +2
-- 이 명령은 text.txt 파일에서 2째줄에서 4째줄까지만 뽑아줍니다.
head 는 문서의 앞부분을 자르는거고 반대로 tail은 뒷부분을 자르는거지요.
먼저 4째줄까지의 앞부분을 자르면 1에서 4까지 잘라질것이고 이걸 파이프 | 로 받아서 다시 2째줄 이후의 꼬리 부분을 자르면 남는건 2~4 줄 부분이 되는 겁니다.
cat text.txt | awk 'NR < 2 { next } { print } NR == 4 { exit }'
awk 로도 가능합니다.
(awk 는 개발자 3명의 이름 이니셜을 모아서 명명되었습니다. 아주 다양한 기능이 존재하는 명령이라 그 기능을 어떤 한 단어로 지정하기도 어렵습니다.)
cat 로 문서를 읽는데 행번호가 2보다 작으면 건너뛰고 크면 인쇄 print 합니다. 행번호가 4 가 되면 인쇄후 종료하게 됩니다.
head, tail 보다는 눈에 잘 들어옵니다. 물론 결과는 같습니다.
몇가지 예제를 설명하고 마차겠습니다.
외장메모리 쓰기 금지를 수정하는 방법과 환경설정에서 설치된 모든 폰트를 가능하게 하는 SPapa 님 트윅을 smali 파일에 적용하는 방법입니다.
파일은 첨부하고 핵심 내용만 설명합니다.
file=platform.xml
scode="android.permission.WRITE_EXTERNAL_STORAGE"
ecode="/permission"
slineno=$( grep -n $scode $file | cut -d":" -f1 )
elines=$( grep -n $ecode $file | cut -d":" -f1 )
해당 구문의 start 라인과 end 라인을 찾으려 합니다.
grep -n 명령은 특정 텍스트를 찾아주고 그 라인 번호를 함께 반환합니다.
357:android.permission.WRITE_EXTERNAL_STORAGE
이런 형식으로 결과를 보여주게 되지요
cut 명령은 -d":" -f1 은 콜론으로 라인을 나누어서 첫번째 부분을 가져온다는 말입니다.
그렇다면 결과는 357 숫자만 남게 되는거지요.
/permission은 그 파일에서 여러개 존재하게 되지요. 그래서 여러개의 숫자가 결과로 남게 됩니다.
for l in $elines ; do
if [ "$l" -ge $slineno ] ; then
elineno=$l
break
fi
done
이 구문은 그 여러개의 숫자 중에서 먼저 검색했던 end 라인값 중에서 start 라인보다 큰 첫번째 숫자를 구하면 해당 부분의 영역 첫줄과 마지막 줄을 알 수 있습니다.
그 줄번호를 알면 앞서 설명했던 방법으로 그 부분만 뽑을 수 있는거지요.
headno=`expr $slineno - 2`
head -n $headno $file > top_file
elineno=$((elineno+1))
tail -n +"$elineno" $file > bottom_file
요건 start 라인의 앞부분까지 top_file 로 자르고
end 라인 앞부분까지 botton_file 로 잘랐습니다.
cat top_file > mfile
cat >> mfile << "EOF"
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
<group gid="sdcard_r" />
<group gid="sdcard_rw" />
<group gid="media_rw" />
</permission>
EOF
cat bottom_file >> mfile
잘라낸 앞부분을 mfie 에 저장하고
이어서 원하는 문구를 뒤에 붙이고
아까 잘라냈던 뒷부분을 마저 붙이면 수정된 텍스트가 생기게 됩니다.
마찬가지 방법입니다
file=FontListPreference.smali
scode1=".method"
scode2="checkFont(Ljava/lang/String;)Z"
ecode1=".end"
ecode2="method"
slineno=$( cat $file | grep -n $scode1 | grep $scode2 | sed "s/[^0-9]//g" )
elines=$( cat $file | grep -n $ecode1 | grep $ecode2 | sed "s/[^0-9]//g" )
시작줄, 끝줄을 찾고
for l in $elines ; do
if [ "$l" -ge $slineno ] ; then
elineno=$l
break
fi
done
해당 end 라인값을 결정하고
head -n $headno $file > top_file
tailno=`expr $tline - $elineno`
tail -n $tailno $file > bottom_file
앞부분과 뒷부분을 뽑아내서 임시저장 하고
cat top_file mysmali.smali bottom_file > new.smali
3개를 하나로 뭉치는 거지요.
뭔가에 적용할 아이디어가 있으신 분은 본인만의 자동화 스크립트에 한번 도전해보십시오.