2014년 5월 21일 수요일

[브레인 스토밍] 아이데오의 브레인스토밍 7원칙

아이데오의 브레인스토밍 7원칙

◎ 초점을 명확히 한다. 즉, 고객의 요구나 서비스에 집중해서 문제를 명확하게 제시한다.
◎ 규칙을 만든다. 예를 들어 '양을 추구한다', '엉뚱한 아이디어를 격려하라', '시각화하라'
    , '판단은 뒤로 미룬다', '한 번에 한 가지씩만 이야기한다' 등.
◎ 아이디어에 번호를 매긴다.
◎ 아이디어 창출이 정체될 때에는 사회자가 다른 이슈로 건너뛸 것을 제안한다.
◎ 아이디어를 기록하기 위해 모든 공간을 활용한다.
◎ 워밍업 시간을 갖는다.
◎ 온몸을 활용해서 스케치를 하거나 프로토타입을 만든다.

2014년 5월 20일 화요일

[Android] 소켓 통신 (android setSoTimeout 과 setConnectionTimeout 의 차이)


안드로이드 소켓 통신 


setSoTimeout setConnectionTimeout 



안드로이드 통신

setConnectionTimeout : 서버가 응답하는 시간의 한도를 정하는 것

setSoTimeout : 서버가 응답하지 않는 경우 소켓의 연결을 끊는 것 (접속 후 먹통이 되는 현상 방지)



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
  HttpClient http = new DefaultHttpClient();
  HttpParams params = http.getParams();
  HttpConnectionParams.setConnectionTimeout(params, 1000 * 60);
  HttpConnectionParams.setSoTimeout(params, 1000 * 300);
  // 서버에 전달할 파라메터 세팅
  ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
  // 서버에 요청정보 입력
  // XML 형식으로 변환 (String)
  String message = null;
  message = converter.toMessage(in);
  nameValuePairs.add(new BasicNameValuePair("message", message));
  HttpPost httpPost = new HttpPost(url);
  httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
  // request
  HttpResponse response = http.execute(httpPost);
  // response
  StringBuffer output = new StringBuffer();
  InputStream instream = response.getEntity().getContent();
  BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
  String line = null;
    while (true) {
         line = reader.readLine();
         if (line == null) {
             break;
         }
         output.append(line + "\n");
     }
  reader.close();
  return output;

[Android] AbsoluteLayout vs RelativeLayout


AbsoluteLayout vs RelativeLayout

  대부분의 화면들은 LinearLayout의 범주에서 벗어나지 않겠지만, 좀 더 유연하고 자유로운 화면의 구현을 위해서는 AbsoluteLayout과 RelativeLayout을 활용할 수 있어야 하겠습니다. 이름만 들어 봐도 Linear보다는 구현이 덜 복잡할 것이 예상됩니다. 오늘은 두가지 모두 다루어 보겠습니다.

  AbsoluteLayout
 말 그대로, 위 아래 양 옆 어디에 어떤 다른 차일드 뷰가 있어도, 상관하지 않고, 부모의 좌측 상단을 0, 0으로 하여 주어진 위치에 차일드를 배치할 수 있도록 한 레이아웃이다. 하지만 한가지 문제점은, 이 레이아웃은, px, dp등 크기가 일정한 단위만이 사용 가능하다. 예를 들어 부모의 가로를 100%으로 하고 20%, 20%에 배치한다거나 하는 일은 불가능하기 때문에, 이것을 이용하여 구현하게 되면 해상도가 다른 폰에 가서는 원하는대로 제대로 표현되기 힘들기 때문에, 특별한 상황이 아니면 사용하지 않는다. 예를 들어 뒷 배경이 정해진 BITMAP파일일 때, 배경에 맞춰서 정해진 위치에 표현할 경우에는 매우 유용하다. bitmap을 부모에 맞춰 늘여서 그리지 않는 한 주어진 위치에 표현될테니 말이다. android:layout_x, android:layout_y라는 두개의 속성만이 존재하는데, 각각이 좌측 상단을 (0,0)으로 한 (x,y)좌표이다. 이 간단한 레이아웃의 예제를 제공하는 것은 지면불리기에 불과하다고 판단되어 패스한다.

  RelativeLayout
 xml등 화면정의파일이 존재하지 않던 시절, 단순 코딩만으로 개발할 때는 좌측 상단부터 오른쪽으로, 위에서 아래로 순서대로 컨트롤들을 배치하면서, A를 그리고, 5px띄어서 B를 그리고, 그렇게 하면서 화면을 구현하곤 했었다. 그런 느낌과 비슷한 레이아웃이 바로 RelativeLayout이다. 차일드들끼리 서로 영향을 주기 때문에, 하나의 길이를 수정하면 전체적으로 같이 조정된다. 이는 잘 설계하면 어떤 레이아웃보다 훌륭할 수 있지만, 너무 복잡한 화면을 하나의 RelativeLayout으로 처리하면, 자칫 너무 복잡해서 하나를 수정하면 다른게 틀어지는 낭패를 볼 수 있으니, 정확히 이해하고 적당히 차일드 레이아웃을 배치하면서 사용하도록 하자.

[Android] 앱버젼 체크

[Android] 앱버젼 체크

1. manifaset.xml 에 어플리케이션의 버젼을 정의힌다. 

2. source에서 

1
2
3
4
5
6
7
String version; 
try {
       PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
       version = pi.versionName;
    
catch(NameNotFoundException e) { }


이것도 충분히 간단한 코드이긴 한데 더 좋은 방법이 있으면 댓글 달아주시기 바랍니다. :)

[Android] App Icon 숨기기

[Android] App Icon 숨기기 

오늘 포스팅 하려고하는 부분은 바로 앱 아이콘을 보이지 않게 하는 부분 입니다^^

왜 설치한 앱을 다시 숨기냐고요??

ㅎㅎ 제가 지금 하는 프로젝트의 특성상 두개의 apk를 사용하기 때문입니다 

그래서 하나의 앱에서 또다른 앱을 호출 하는 형식으로 진행 되거든요

그래서 불려지는 앱은 아이콘이 없어야하는 문제가 있었습니다^^


결론.... AndroidManifest.xml 파일에 한줄만 제거해주면... 너무 간단히 앱아이콘을 숨길수 있네요...

소스는 이러합니다.

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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testhello"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.testhello.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>
 


위와같은 일반적인 manifest 파일에서 22 line 을 제거 해주기만 하면 

앱 아이콘은 사라지지만 다른앱을 통해 호출이 가능한 상태가 됩니다^^


일반적으로는 자주 사용되지는 않겠지만

우선 지금은 나에게 필요했던 부분이기에 포스팅으로 남깁니다^^

다들 즐거운 월요일 되세요~

[Android] Android Intent 값 받아오기

[Android] Android Intent 값 받아오기 

Intent

다른 액티비티를 시작하려면 액티비티의 실행에 필요한 여러가지 정보들을 보내주어야 합니다.
이러한 정보를 Activity에 실어 보낼 수 있습니다.
Activity들은 Stack 자료구조에 저장됩니다.
그러므로 Back을 누르면 스택에서 현재 Activity를 Pop시키면서 이전 Activity로 돌아갈 수 있습니다.

본 예제에서는
Intent를 사용한 간단한 Activity간의 이동을 다루며
putExtra를 사용해서 값을 전달하는 기본 구현을 해 보도록 하겠습니다.

 


본 화면과 같이 간단한 Editview, Button을 포함한 MainActivity를 LinearLayout으로 만들어 줍니다.

 

또한 간단한 Editview, Button을 포함하는 SubActivity를 LinearLayout으로 만들어 줍니다.

자 여기서 MainActivity 에서 SubActivity로 이동 후, SubActivity의 EditText에 문자열을 입력하고
Input버튼을 누르면, 화면이 SubActivity에서 MainActivity로 이동하고,  문자열 값이 MainActivity의 EditText에 
전달되도록 해 보겠습니다.

그러기 위해서는 첫번째

MainActivity의 버튼에 Event를 매겨봅시다.
 

보기와 같이 onCreate Method를 정의합니다.
버튼을 클릭하면 Intent를 만드는데
여기서 생성자에 들어가는 파라미터는 순서대로 현재 액티비티, 옮길 액티비티 입니다.

startActivityForResult 메서드에는 Intent 시, 1이라는 값을 넘긴다는 것입니다.




두번째로 SubActivity를 정의합니다.
 

보기와 같이 버튼에 이벤트를 달았는데요
putExtra메서드를 사용하여 "INPUT_TEXT"의 이름으로 EditText의 값을 가져와서 넘깁니다.
또한 결과값을 Result_OK로 설정하지요.
finish(); 는 Activity의 종료를 의미합니다.

그렇다면, 버튼을 누르면 다시 MainActivity로 넘어가게 됩니다.

이 때, 가만히 놔두면 MainActivity의 EditText값이 변하지 않는데요
 

보기와 같이 onActivityResult 메서드를 재정의 해 주어야 합니다.
requestCode(MainActivity에서 SubActivity로 이동할 때 설정했던 1) 이 1이고,
resultCode(SubActivity에서 종료 전 설정했던 Result값) 이 RESULT_OK이면
EditText의 값을 정합니다.

파라미터로 data라는 Intent가 전달되는데요,
이 파라미터에 getStringExtra("INPUT_TEXT")(SubActivity에서 설정했던 값)을 입력해주면

아래와 같이 값이 성공적으로 전달된 것을 볼 수 있답니다.
참쉽죠?
 


[Android] Platform key signing 완벽 분석

출처 kimyow | 사랑혜영
원문 http://kimyow.blog.me/50116380850
 

[Android] Platform key signing 완벽 분석


Platform key signing 을 하는 이유는 뭘까?

왜 굳이 Platform key 로 signing 을 해야 할까?

일반적인 apk 의 경우, (일반 개발자, 3rd party 가 개발한 APK) 자신이 만든 apk 를, data 영역에 install 할 수 있으며, 또는 rooting 한 폰의 system 영역에 설치할 수 있고, 이를 실행할 수 있다.

여기서 일반적인 apk 란, 통상적을 제공되는 sdk 에서 개발 된 apk 를 말한다.
(Vendor가 아닌, 일반적인 모든 개발자가 Eclipse 등 SDK를 사용하여 개발한 Application) 

Full image build 과정에서 생성되는 System image(Framework.jar)를 사용하면, 소위말하는 Internal or Hidden API 를 사용하여 build 할 수 있다.

SDK 로 제공되는 android.jar 에는 포함되지 않는 API(method) 들이 많다. 
이는 Android가 일반 개발자에게는 open 하지 않는 기능들이라고 봐도 좋다.

오직 Device 를 만들어서 파는 Vendor(삼성/LG)들만이 사용할 수 있다.

Settings.apk 의 경우,

타 모델의 apk 또는 source 를 구한다 한 들, 쉽게 자신의 phone 에 설치 & 실행이 안 될 것이다.
(Setting 만이 가지고 있는 특정 기능을 포기한 후 build 한다면, 가능하다.)

이미 당신이 가지고 있는 폰은 Vendor 가 User mode 로 build 한, 특정 key 로 signing 된 image 를 사용하기 때문이다.
( Debug or Engineer 모드로 build 된 image 가 탑재된 상태로 시장에 출시되지 않겠죠? )

User mode build 시, Vendor 는 android 에서 제공되는 known key (보통, \build\target\product\security\ 안에 있다.) 로 signing 하지 않으며, 각자의 unique 한 key 를 만들어서 signing 한다. 개발 편의를 위해서 default key 로 signing 하기도 하는데, 이는 eclipse 가 build 시 signing 하는 key 와 동일하다.

즉, Vendor 입장에서는 개발 단계와 양산 단계의 signing key 가 다른 것이다.

System 권한이 필요한 Setting 의 경우, Platform key 로 signing 후 설치된다. System과 동일한 uid 를 가져야 동일한 권한으로 data/code 사용이 가능하며 이를 위해서는 system 과 동일한 platform key 로 signing 되어야 한다.

하지만, 이미 당신이 가지고 있는 device(phone) 의 platform key 를 가지고 있지 않은 이상, 아무리 source build 를 성공해도 만들어진 Settings.apk 를 설치하기란 불가능하다.
(설치하려고 하면, INSTALL_FAILED_SHARED_USER_INCOMPATIBLE error 가 뜰 것이다.)

물론, 위에서 언급했듯이 Setting 만의 특정 기능을 뺀다면 가능하다.

Setting 만의 특정 기능이란, 타 application 을 memory 상에서 깨끗하게 kill 할 수 있는 기능이다.

이는 위에서 언급한 internal api 를 사용해야 하므로, 3rd party application 에선 사용이 불가능하며, system 권한/자격이 필요한 기능이다.

System 권한, 자격을 포기한다면, 굳이 platform key 로 signing 할 필요 없으며, 일반적인 application 으로써, 어떤 device 든지 기 설치되어 있는 settings.apk 만 확실히 제거한 후, 당신이 빌드한 새로운 settings.apk를 재설치해서 사용이 가능하다.

이 system 자격, 권한을 포기한다는 의미가, AndroidManifest.xml 에서 속성으로 명시된,
android:sharedUserId="android.uid.system" 항목을 삭제하는 것이다.

위 의미는 system process 와 같은 uid 를 사용하므로써, system process 의 code & data 를 똑 같이 공유할 수 있는 권한을 해당 application 에게 준다는 의미이다.

따라서 위 항목을 지우고 build 한 apk 를 설치하면 아주 자~~알 설치될 것이다.

하지만,~~ Settings > Applications >Manage applications 에서 "Force stop" 버튼을 클릭 하는 순간 unexpected error, 즉 setting application 이 죽을 것이다.

System 자격이 있는 넘이 호출해야 할 함수를 자격이 없는 application이 호출했기 때문에 Permission error 가 나는 것이다.

대표적인 Internal api method 인, ActivityManager 의 forceStopPackage() 를 예로 들어보자.- Internal API이므로, 일반 개발자에게는 open 되어 있지 않은 함수다.

보통 Market에서 download 받아 설치하는 일반적인 system application의 경우(TaskManager), ActivityManager.killBackgroundProcesses() 로 application 을 kill하는데, 이는 application 우선순위가 Background 이하인 application 만 kill 하는 제약을 가지고 있다.(Visible, Foreground, Service 우선순위는 완벽하게 kill 할 수 없다.)

이에 반해 ActivityManager.forceStopPackage() 함수는 아무런 제약 사항없이 대상이 되는 application 을 메모리상에서 깨끗히 지우는 기능을 한다.

이 함수를 실행하기 위해서는 permission 이 필요한데, 
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"></uses-permission>
라고 AndroidManifest.xml 에 명시해줘야 한다.

이렇게 해서 build 된 apk 를 install 한 후, 실행 하면 하기와 같은 exception 이 발생한다.

==================================================================

07-21 10:38:13.480: WARN/ActivityManager(1981): Permission Denial:forceStopPackage() from pid=3565, uid=10110 requires android.permission.FORCE_STOP_PACKAGES
07-21 10:38:13.503: ERROR/AndroidRuntime(3565): FATAL EXCEPTION: main
07-21 10:38:13.503: ERROR/AndroidRuntime(3565): java.lang.SecurityException: Permission Denial: forceStopPackage() from pid=3565, uid=10110 requires android.permission.FORCE_STOP_PACKAGES
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Parcel.readException(Parcel.java:1260)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Parcel.readException(Parcel.java:1248)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.app.ActivityManagerProxy.forceStopPackage(ActivityManagerNative.java:2564)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.app.ActivityManager.forceStopPackage(ActivityManager.java:968)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.lge.lmk.activities.RunningProcessActivity$4.onClick(RunningProcessActivity.java:850)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:158)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Looper.loop(Looper.java:123)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.app.ActivityThread.main(ActivityThread.java:4668)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at java.lang.reflect.Method.invokeNative(Native Method)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at java.lang.reflect.Method.invoke(Method.java:521)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at dalvik.system.NativeStart.main(Native Method)
==================================================================


"android.permission.FORCE_STOP_PACKAGES" Permission 을 명시해 줬는데 왜 Permission error가 날까?

이 함수를 call 하는 application쪽에 System process 의 권한이 없기 때문이다.

system process 와 동일한 권한을 갖기위해서는?

AndroidManifest.xml 파일의 manifest attribute 에 하기와 같이 지정해 주면 된다.
android:sharedUserId="android.uid.system"

이 application process 의 uid 를 system 과 공유함으로써, system 과 동일한 권한을 갖겠다는 의미다.

참 편리하게 system 권한을 가질 수 있다고 생각할 수 있지만, 이는 어디까지 platform(system)  과 signature 가 같을 때의 경우에만 해당된다.

다시한번 언급하자면, 
모든 사용자가 구입한 폰은 각 Vendor 측의 고유 key로 signing 된, User mode 로 빌드 된 image 가 탑재 되었고, 각 모델별로 고유한 platform key 로 signing 되었기 때문에, 아무리 rooting 을 했건, 뭐를 했건간에, User mode 로 빌드 된 image의 key 를 바꿀 순 없다.
(Vendor 측에 아는 사람이 있어 debug 나, engineer 모드로 빌드된 image 를 구할 수 있다면??)

전체 이미지 빌드 타임에 system 과 data 영역에 들어갈 모든 APK는, 싹 다 각각 Android.mk에 명시된 key 값으로 signing 한다.

때문에, Signature 가 Platform과 맞지 않은 Settings application 을 폰에 탑재하는 순간, 아래와 같은 logcat msg 와 함께, 해당 apk 는 launcher 에서 볼 수 없을 것이다.(PackageManager 가 package loading 실패)
====================================================================
07-21 10:56:36.046: WARN/PackageManager(1981): Package com.test.application shared user changed from <nothing> to android.uid.system; replacing with new
07-21 10:56:36.054: WARN/PackageManager(1981): Signature mismatch for shared user : SharedUserSetting{462749e8 android.uid.system/1000}
07-21 10:56:36.054: ERROR/PackageManager(1981): Package com.test.application has no signatures that match those in shared user android.uid.system; ignoring!

====================================================================

또는,(아래는 살짝 다른 유형의 error 다.)
====================================================================


08-09 09:47:06.054: ERROR/PackageManager(1973): Package com.test.application signatures do not match the previously installed version; ignoring!
08-09 09:47:06.257: INFO/IQClient(2030): submitHW03 -  status- 2 level- 74
====================================================================


system 쪽과 signature mis-match 가 나서 이 어플을 loading 할 수 없다는 의미이다.

해결방법은 해당 어플도 똑같이 platform signing 을 해주는 방법밖에 없다.

그래야 system 권한을 얻을 수 있다는 의미이다.

하기와 같이 platform key 를 어디선가 구해와서 signing 해주면 된다.
(당연히 아래 platform key 가 당신의 device 에 flashing 되어 있는 image 의 signed platform key 와 동일해야 한다.)

Platform key 는 어디서 구할까...??? 해당 모델의 Vendor 만이 알 수 있다.

java -jar signapk.jar platform.x509.pem platform.pk8 Unsigned.apk Signed.apk

위 명령어로 생성된 Signed.apk 를 설치해주면 System 권한으로 internal api 사용이 가능하며 원하는 모든 기능이 정상 동작 될 것이다.

[Android] Dalvik VM

Dalvik VM의 개괄적 Source 분석
Dalvik VM은 Android에서 돌아가는 VM이다. 이전에도 포스트 한바와 같이 

Phoneme project, harmony의 코드와도 외형과 핵심 구조체 등이 상당히 유사하다.

이전 포스트 이후 harmony를 대략적으로 분석해 보았으며 

결론은 대략 비슷한데 phoneme와 harmony는 상당히 일치하고 dalvik은 harmony를

바탕으로 만들어진 것이 맞다고 봐야 할듯하다. 

직접적인 코드 외에도 초기화시 로드하는 핵심클래스가 동일한 것들도 몇가지 있다.

예를 들면 다음과 같은 것들이 있다. ( dalvik/vm/Init.c의 dvmJniStartup()을 참고하자. )

org/apache/harmony/luni/platform/PlatformAddress.java
org/apache/harmony/luni/platform/PlatformAddressFactory.java
org/apache/harmony/nio/internal/DirectBuffer.java

간단히 dalvik vm이 실행되는 process를 정리해 보자.

main() -> option을 위한 메모리 할당 -> option 파싱 -> JNI_CreateJavaVM() -> findClass()
-> GetStaticMethodID() -> CallStaticVoidMethod() -> DetachCurrentThread() -> DestroyJavaVM() 

dalvik/vm/main.c의 main() 함수가 entry point이다. 대략 위와 같은 과정을 거치는데 거의 모든 

초기화의 과정이 JNI_CreateJavaVM()에서 이루어진다. 

이후에는 실행시킬 클래스를 findClass()로 실행시킬 main 메소드를 GetStaticMethodID()로 찾는다.

이후 CallStaticVoidMethod()로 class의 main 메소드를 실행시키면 이후의 과정은 main 메소드가

종료할때까지는 intepreter와 dex 파일과의 상호작용이라 봐야 하겠다. 

종료는 DetachCurrentThread()와 DestroyJavaVM()의 두가지 과정으로 볼수 있는데 

Exception에 의한 종료와 정상 종료 크게 두가지 경우가 있을수 있다.

jvm의 경우 일반적으로 따로 Thread를 사용하지 않아도 최소 1개의 쓰레드를 가지고 있는데 

이를 main thread라고 부른다. 일반적으로 static void main(String[] args)으로 선언한 메소드의

코드를 실행하는 역할을 한다고 보면 된다. 


dalvik vm의 전체개요를 이해하기 위해서는 JavaVM, JNIEnv의 두가지 구조체를 이해하는 것이

상당히 중요한데 코드에서는 다음과 같이 정의되어 있다. 

#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif

C로 정의된 JNINativeInterface나 JNIInvokeInterface의 경우 디바이스 드라이버를 개발해

보신분들은 상당히 익숙한 구조일듯한 변수와 함수 포인터의 집합으로 구조체를 만들어 놓았다.

정리해 보면

JNIEnv는 대략적으로 dalvik vm의 환경 설정과 관련된 함수들이 쭈욱 모아져 있는데 

코드를 분석하기 위해서는 우선 CallMethod 계열, GetMethod 계열, FindClass 부분을 우선적으로

보는 것이 좋을 것이다.

JavaVM의 경우는 

DestroyJavaVM, AttachCurrentThread, DetachCurrentThread, GetEnv, AttachCurrentThreadAsDeamon

등의 단촐하게 5가지만 있다. 

JNIEnv와 JavaVM 구조체의 함수 포인터들은 각각

JavaVM: main -> JNI_CreateJavaVM()에서 gInvokeInterface의 값으로
JNIEnv: main()->JNI_CreateJavaVM()에서 gNativeInterface의 값으로 

셋팅된다. 


이후의 과정은 서술한 바와 같이 class를 찾고 class의 static main 메소드를 찾고 이를 호출하는

과정이다. 실제 코드는 다음과 같이 되어 있다.

(*env)->CallStaticVoidMethod(env, startClass, startMeth, strArray);


gInvokeInterface에서 찾아보아도 호출하는 함수의 실제 이름도 CallStaticVoidMethod로 동일하다.

CallStaticVoidMethod는 내부에서 CallStaticVoidMethodV를 호출하는데 이함수는 crags, scope

등으로 찾으려하면 잘 나오지 않는데 이는 코드의 선언이 다음처럼 되어 있기 떄문이다. 



 "##"은 변수 또는 함수의 이름을 접합시켜 주는 역할을 한다. 

위의 코드에서는 CallStatic##_jname##MethodA 처럼 사용됐는데 _jname이 컴파일 타임에 결정되어

반드시 결정되어 있어야만 하며 

예를 들어, CALL_STATIC(jbyte,Byte,result.b, false); 의 코드가 있다면

CallStaticByteMethodA와 같은 함수선언이 된것과 같은 효과가 있다. 

그럼 CallStaticVoidMethodV를 잠깐 살펴보자. 

JNI_ENTER()로 쓰레드의 상태를 변경해준후 바로 dvmCallMethodV()를 호출해준다. 

프레임에 공간을 확보한후에 argument를 처리하고 dvmInterpret()를 호출하여 

본격적으로 dex의 opcode의 처리를 시작한다. 

여기서 부터는 다시 복잡해 지므로 자바의 메소드 호출 방식 및 메소프 스택을 

처리하는 법에 관해서는 다음글에서 이어서 포스트한다. 


[Android] SDCard 남은 용량 체크하기

[Android] SDCard 남은 용량 체크하기

간략히 사용방법에 대해서 포스팅 하자.



아래와 같이 임포트 해준다.
1
2
3
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;

사용되는 실 사용 코드이다.
1
2
3
           StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        long bytesAvailable  =(long) stat.getFreeBlocks()* (long)stat.getBlockSize();
        Log.d("########"">>>> bytesAvailable : " + bytesAvailable);


위와같이 사용하면 로그 기록에 남은 용량에 대해서 byte 단위로 나오게 된다^^

이상~ ㅎㅎ

[JAVA] HashMap

[JAVA] HashMap

#. HashMap이란?

  • HashMap은 Map을 구현한다. Key와 value를 묶어 하나의 entry로 저장한다는 특징을 갖는다. 그리고 hashing을 사용하기 때문에 많은양의 데이터를 검색하는데 뛰어난 성능을 보인다.


  • Map 인터페이스의 한 종류로 ( "Key", value) 로 이뤄져 있다.
  • Key값을 중복이 불가능 하고 value는 중복이 가능. value에 null값도 사용 가능하다.
  • 멀티쓰레드에서 동시에 HashMap을 건드려 Keyvalue값을 사용하면 문제가 될 수 있다. 멀티쓰레드에서는 HashTable을 쓴다

#. HashMap 생성자 / 메서드

생성자 / 메서드
설명 
HashMap()
- HashMap 객체를 생성
ex) HashMap<String , Integer> map = new HashMap<String , Integer>();
      Map<String, Integer> map = new HashMap<String, integer>();
HashMap(int initlalCapacity)
- 지정된 값을 초기 용량으로 하는 HashMap객체를 생성한다.
HashMap(int initlalCapacity, float loadFactory)
- 지정된 값을 초기용량과 load factory의 HashMap 객체를 생성한다. 
HashMap(Map m) 
- 주어진 Map에 저장된 모든 요소를 포함하는 HashMap을 생성한다. 
void clear()
- HashMap에 저장된 모든 객체를 제거한다. 
ex) map.clear();
Object clone()
- 현재 HashMap을 복제하여 반환한다. 
ex) newmap = (HashMap)map.clone();
boolean containsKey(Object Key)
- HashMap에 지정된 키(Key)가 포함되어 있는지 알려준다. 
boolean containsValue(Object Value)
- HashMap에 지정된 값(Value)가 포함되어 있는지 알려준다. 
Set entrySet()
- HashMap에 저장된 Key - Value갑슬 엔트리(키와 값을 결합)의 형태로 Set에 저장하여 반환
ex) map.put("A", 1);
      map.put("B", 2);
      map.put("C", 3);
      Set set = map.entrySet();
      System.out.println("set values are" + set);
      (result) set values : [A=1,B=2,C=3]
Object get(Object Key)
- 지정된 Key 의 값을 반환한다. 
ex) map.put("A", 1);
      map.put("B", 2);
      map.put("C", 3);
      String val = (String)map.get("B");
System.out.println("Value for key B is: " + val);

(result) Value for key B is 2
bloolean isEmpty
- HashMap이 비어있는지 확인한다.
ex) boolean val = map.isEmpty();
Set keySet()
- HashMap에 저장된 모든 키가 저장된 Set을 반환한다.
ex) map.put("A", 1);
      map.put("B", 2);
      map.put("C", 3);
      Set keyset = map.keySet();
      System.out.println("Key set values are" + keyset);
      (result) Key set values are [A,B,C]
Object put(Object Key, Object Value)
- HashMap에 키와 값을 저장.
ex) map.put("A", "aaa");
      map.put("B", "bbb");
      map.put("C", "ccc");
void putAll(Map m)
- Map에 해당하는 모든 요소를 HashMap에 저장한다. 
Object remove(Object Key)
- HashMap에서 지정된 키로 지정된 값을 제거한다.
ex) map.remove("key");
int size()
- HashMap에 저장된 요소의 개수를 반환한다. 
Collection values()
- HashMap에 저장된 모든 값을 컬렉션 형태로 반환한다. 









#. 사용

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

pubilc class HashMapDemo
{
public static void main(String[] args) 
{
HashMap<String, Integer> fruitMap = new HashMap();
fruitMap.put("사과", 1000);
fruitMap.put("배", 2000);
fruitMap.put("자두", 3000);
fruitMap.put("수박", 4000);

// get() --> Key에 해당하는 Value를 출력한다.
System.out.println( fruitMap.get("자두") );   // 3000

        // values() --> 저장된 모든 값 출력
System.out.println( fruitMap.values() ); // [1000, 2000, 3000, 4000]

// HashMap에 넣은 Key와 Value를 Set에 넣고 iterator에 값으로 Set정보를 담에 준다.
// Interator itr = fruitMap.entrySet().interator(); 와 같다.
Set<Entry<String, Integer>> set = fruitMap.entrySet();
Interator<Entry<String, Integer>> itr = set.interator();
while (itr.hasNext())
{
Map.Entry<String, Integer> e = (Map.Entry<String, Integer>)itr.next();
System.out.println("이름 : " + e.getKey() + ", 가격 : " + e.getValue() + "원");
}
}

결과 :
이름 : 사과, 가격 : 1000원
이름 : 배, 가격 : 2000원
이름 : 자두, 가격 : 3000원
이름 : 수박, 가격 :  4000원


참고 >