Android 에서 로 그 를 안전하게 인쇄 하 는 방법 에 대한 자세 한 설명

머리말
Android 개발 과정 에서 Demo 를 쓰 든 실전 프로젝트 를 쓰 든 데 이 터 를 기록 하 는 데 사용 할 로 그 를 인쇄 합 니 다.디 버 깅 을 했 습 니 다.Android 의 로그 도구 류 는 Log 입 니 다.이 종 류 는 로 그 를 인쇄 하 는 방법 을 제공 합 니 다.다섯 개의 등급,v,d,i,w,e 는 각각 다른 적재량 이 있다.
로 그 를 인쇄 하 는 방법 에 대해 이야기 할 때?많은 사람들 이 이것 이 쉽 지 않다 고 생각 할 것 이다.바로android.util.Log이런 종 류 를 사용 하면 되 지 않 을 까?그러나 로 그 는 매우 민감 한 정보 에 속한다.역방향 엔 지 니 어 는 프로그램 을 역방향 으로 할 때 프로그램의 각종 출력 을 포착 한 다음 에 추측 을 해서 덩굴 을 타고 참 외 를 만 져 서 필요 한 정 보 를 얻어 야 한다.로그 가 새 어 나 가면 문 이 열 리 는 것 과 다 름 없 으 며,프로그램 을 풀 어 내 는 것 은 무인지경 에 들 어 가 는 것 과 같다.
안전 의 개념 은 원래 상대 적 인 것 이다.만약 에 프로그램 을 푸 는 대가 가 해결 할 수 있 는 가치 보다 훨씬 크다 면 프로그램 은'안전 하 다'고 볼 수 있다.프로그램의 안전성 을 높이 기 위해 로 그 를 인쇄 할 때 무엇 을 주의해 야 하 는 지 분석 해 보 자.
우선 대부분의 회사 와 개발 자의 방법 을 살 펴 보 자.
로그 스위치+로그 클래스
release 버 전에 서 로그 출력 이 없 기 위해 서 가장 간단 한 생각 은 모든 인쇄 로그 의 문 구 를 하나의if(DEBUG)문구 에 넣 는 것 입 니 다.일상 적 으로 개발 할 때 DEBUG 스위치 가 열 리 고 정식 버 전 을 발표 할 때 이 스위치 를 닫 으 면 됩 니 다.대체적으로 다음 과 같 습 니 다.

// LogUtil.java
public class LogUtil {
 private static boolean DEBUG = true;//         false
 
 public static void d(String tag, String msg) {
  if (DEBUG) android.util.Log.d(TAG, msg);
 }

 //   debug  
}
다음은 진실 한 예 를 들 어 외국 의 apk,이름 은 powerclean 입 니 다.가방 이름:com.lionmobi.powerclean;우 리 는 이 가방 을 설치 합 니 다.로그 출력 이 없 는 것 이 정상 입 니 다.그리고 우 리 는 이 apk 를 거 슬러 올 라 갑 니 다.몇 가지 종 류 를 대충 뒤 져 보 니 로그 출력 과 유사 한 곳 이 많 습 니 다.
로그 출력 그림
우 리 는 이 x 라 는 종 류 를 열 었 다.비록 헷 갈 렸 지만 뜻 은 매우 분명 하 다.우리 위의 생각 과 같다.

package com.lionmobi.util;

import android.util.Log;

public class x {
 private static boolean a;

 static {
  x.a = false;
 }

 public static void d(String arg1, String arg2) {
  if(x.a) {
   Log.d(arg1, arg2);
  }
 }

 public static void e(String arg1, String arg2) {
  if(x.a) {
   Log.e(arg1, arg2);
  }
 }

 public static void i(String arg1, String arg2) {
  if(x.a) {
   Log.i(arg1, arg2);
  }
 }
}
이것 은 진실 한 예 이 고 이 app 의 사용자 가 적지 않다.다음은 이런 방식 에 무슨 문제 가 있 는 지 살 펴 보 자.
정적 컴 파일 로그 스위치 열기
위의 방식 에 문제 가 있 습 니 다.release 버 전에 서 로그 출력 이 없 는 것 은 사실 입 니 다.그러나 출력 로그 의 코드 는 여전히 존재 합 니 다.실행 되 지 않 았 을 뿐 입 니 다!(if 조건 이 성립 되 지 않 음)그래서 이 코드 들 을 실행 시 킬 방법 이 있 습 니까?쉽게 말 하면 release 버 전에 서 이 DEBUG 변 수 를 true 로 만 들 수 있 습 니까?그럼요!그리고 방법 도 간단 하 다.
우 리 는 apktool 을 사용 하여 이 apk 의 smali 코드 를 역 컴 파일 할 수 있 습 니 다.그리고 위의 역 컴 파일 은 이 로그 류 의 위 치 를 알려 줍 니 다.com.lionmobi.util.x우 리 는 이x.smali파일 을 열 었 습 니 다.내용 은 다음 과 같 습 니 다.

.class public Lcom/lionmobi/util/x;
.super Ljava/lang/Object;


# static fields
.field private static a:Z


# direct methods
.method static constructor <clinit>()V
 .locals 1

 const/4 v0, 0x0 #    0x1 (True)

 sput-boolean v0, Lcom/lionmobi/util/x;->a:Z #     

 return-void
.end method

.method public static d(Ljava/lang/String;Ljava/lang/String;)V
 .locals 1

 sget-boolean v0, Lcom/lionmobi/util/x;->a:Z

 if-eqz v0, :cond_0

 invoke-static {p0, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

 :cond_0
 return-void
.end method

.method public static e(Ljava/lang/String;Ljava/lang/String;)V
 .locals 1

 sget-boolean v0, Lcom/lionmobi/util/x;->a:Z

 if-eqz v0, :cond_0

 invoke-static {p0, p1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I

 :cond_0
 return-void
.end method

.method public static i(Ljava/lang/String;Ljava/lang/String;)V
 .locals 1

 sget-boolean v0, Lcom/lionmobi/util/x;->a:Z

 if-eqz v0, :cond_0

 invoke-static {p0, p1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

 :cond_0
 return-void
.end method
a 라 는 정적 변 수 는 바로 우리 의 스위치 입 니 다.그것 의 초기 화 는 어느 정적 코드 블록 에 있 습 니까?부분 변수 0x0 을 새로 만 들 고 a 에 값 을 부여 합 니 다.그래서 우 리 는 이 0x0 을 0x1 로 수정 하고 이 스위치 를 열 었 다.아주 간단 합 니 다.다음 에 수 정 된 smali 를 포장 한 다음 에 새로운 실행 가능 한 apk 에 서명 합 니 다.실행 해 봐.결과 봐.과연 많은 로그 가 출력 되 었 습 니 다.프로그램 이 무엇 을 하고 있 는 지 스스로 알려 주 었 습 니 다.맞 힐 필요 가 없습니다.나 는 마음대로 그림 을 캡 처 해서 느 꼈 다.

누 출 된 로그 정보
release 버 전에 로그 코드 가 포함 되 지 않도록 합 니 다.
위의 분석 을 통 해 우 리 는 프로그램 이'로그 보안'이 필요 하 다 면 release 버 전에 출력 로그 코드 가 존재 하지 말 아야 한 다 는 결론 을 얻 었 다.
어떻게 이 점 을 할 수 있 습 니까?우 리 는 개발 할 때 로 그 를 정상적으로 인쇄 하 는 도 구 를 만 들 수 있다.버 전이 필요 하면 로 그 를 인쇄 하 는 모든 문장 코드 를 삭제 합 니 다.코드 는 매우 간단 해서 정규 표현 식 을 사용 하면 할 수 있다.
사실 우 리 는 다른 도 구 를 사용 하여 이 유사 한 기능 을 실현 할 수 있다.바로 proguard 입 니 다.이 도 구 를 언급 하면 많은 사람들 이 그 가 코드 가 혼 란 스 러 운 도구 라 고 생각 할 뿐이다.실제로 그것 은 너 에 게 쓸모없는 코드 를 제거 하 는 데 도 도움 을 줄 수 있다!어떤 코드 가 무용 코드 입 니까?

if (true) {
 // statement;
}
이와 같이 정적 컴 파일 을 할 때'영원히 실행 되 지 않 는 코드'로 여 겨 지면 쓸모없는 코드 로 여 겨 지고 이 도구 에 의 해 직접 최적화 되 며 생 성 된 class 파일 에 이 if 문 구 는 바로 없습니다.이 기능 은 우리 의 요구 에 완벽 하 게 부합된다.우 리 는 출력 로그 의 코드 를 이러한 if 구문 으로 둘러싸 고 release 를 할 때 이 도구 로 헷 갈 릴 것 입 니 다.그리고 release 버 전에 서 모든 출력 로그 의 코드 가 없습니다!예전 처럼 그림 자 를 남기 지 않 고 일 만 하지 않 는 다.
올 바른 방법
마지막 으로,우리 의 모든 인쇄 로그 의 문장 은 다음 과 같 아야 한다.

private static final boolean DEBUG = true; //    static final      ,          ;  if 

if (DEBUG) {
 android.util.Log.d(TAG, "msg to print");
}
그리고 proguard 최적화 코드 를 사용 하면 됩 니 다.
간단 해 보이 고 최초의'로그 스위치'와 다 를 것 이 없 는 것 같 습 니 다.자세히 분석 해 보 세 요.
로그 스위치 는 정적 상수 여야 합 니 다.
정확 한 방법 과 최초의 로그 스위치 를 비교 해 보 세 요.하 나 는 정적 변수 이 고 하 나 는 정적 상수 입 니 다.상수 라면 영원히 변 하지 않 습 니 다.DEBUG 변수 가 False 일 때 proguard 는 이 부분 코드 가 절대 실행 되 지 않 을 것 이 라 고 생각 할 수 있 습 니 다.그러면 로 그 를 인쇄 하 는 문 구 는 최적화(삭제)될 것 입 니 다.변수 라면 실행 기간 에 값 을 바 꿀 수 있 습 니 다.
로그 클래스 버 리 기
만약 에 우리 가 정적 상수 코드 블록 과 proguard 최적화 코드 기술 을 사용 했다 고 가정 합 니 다.하지만 여전히 위의 로그 류 기술 을 사용 하면 무슨 일이 일어 날 까?

public class LogUtil {
 private static final boolean DEBUG = false;

 public static void d(String tag, String msg) {
  if (DEBUG) android.util.Log.d(tag, msg);
 }
}
나 는 demo 를 썼 다.스스로 포장 한 후에 역 컴 파일 해서 이 로그 류 를 다음 과 같이 얻 었 다.(보기 편 하도록 헷 갈 리 지 않 았 다)

package com.example.test.app;

public class LogUtil {
 private static final boolean DEBUG;

 public LogUtil() {
  super();
 }

 public static void d(String tag, String msg) {
 }
}
if 코드 블록 이 없어 서 로 그 를 출력 하지 않 는 것 을 보 았 습 니 다.하지만 이런 곳 을 살 펴 보 자!

눈 가리 고 아 웅 하 는 일지
LogUtil.d의 호출 은 눈 가리 고 아 웅 하 는 것 과 다름없다.해독 자 는android.util.Log와 같은 종류의 로 그 를 출력 할 수 없 지만,당신 이 있 는 이 호출 은 다른 사람 에 게 당신 이 무엇 을 하고 있 는 지 알려 줍 니 다.따라서 로그 의 출력 을 차단 하려 면 제거 할 로 그 를 if 코드 블록 으로 직접 포함 해 야 합 니 다.위의 로그 류 는 최적화 되 어야 합 니 다.바로:

if (DEBUG) {
 LogUtil.d(TAG, "msg");
}
여 기 는 쓸데없는 짓 이 아 닙 니까?일지 류 를 쓰 는 것 은 반복 적 으로 쓰 고 싶 지 않 습 니 다if (DEBUG).여 기 는 이 말 을 숨 기기 위해 도망 칠 수 없습니다.하지만 스님 이 절 을 빠 져 나 갈 수 없어 서 죄송합니다.이런 방법 으로 는 정 보 를 완전히 숨 길 수 없습니다.로그 류 패키지 로그 코드 를 버 려 야 합 니 다!
양손 해방
로그 보안 을 위해 출력 로그 마다 if 문 구 를 쓰 는 것 은 귀 찮 지 않다 는 말 이 있 을 지도 모른다.정말 반 인간 이 야,난 게 을 러!실제로 몇 줄 의 코드 를 적 게 쓰 려 면 재 활용(코드 등급,예 를 들 어 위의 로그 류)을 선택 할 수도 있 고 생 성(코드 직접 생 성)을 선택 할 수도 있 습 니 다.원 프로 그래 밍 을 지원 하 는 언어 에서 코드 를 만 드 는 것 은 흔히 볼 수 있 는 일이 다.예 를 들 어 C++의 모드 원 프로 그래 밍 과 ruby 가 자랑 하 는 DSL 능력 이다.여 기 는 그렇게 크 지 않 습 니 다.코드 로 코드 를 만 듭 니 다.우 리 는 직접 편집 기 를 통 해 코드 를 몇 줄 덜 쓰 는 것 을 도 왔 습 니 다.
IDEA/Android Studio
live template 기능 을 사용 할 수 있 습 니 다.예 를 들 어 제 방법 은 ifd 의 template 를 쓰 는 것 입 니 다.제 가 ifd 를 입력 할 때마다 자동 으로 if 문 구 를 펼 치고 커서 는 맨 중간 에 멈 추 는 것 입 니 다.
live template 를 사용 하여 입력 을 간소화 합 니 다.
vim/emacs
매크로 녹음 기능 을 사용 하여 위의 live template 를 실현 할 수 있 습 니 다.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기