아래 3가지 방법중에 하나를 통해서 썸네일 이미지를 가져올 수 있다.


1. ContentResolver를 통해 직접 썸네일 이미지를 가져오기

MINI_KIND: 512 x 384 thumbnail

MICRO_KIND: 96 x 96 thumbnail


Bitmap bitmap = MediaStore.Images.Thumbnails.getThumbnail(

getContentResolver(), selectedImageUri,

MediaStore.Images.Thumbnails.MINI_KIND, null );


2. 썸네일 Uri가져오기

Cursor cursor = MediaStore.Images.Thumbnails.queryMiniThumbnail(

                             getContentResolver(), selectedImageUri,

                             MediaStore.Images.Thumbnails.MINI_KIND,

                             null );

if(cursor.moveToFirst() && cursor.getCount() > 0 ) {

String uri = cursor.getString( cursor.getColumnIndex( MediaStore.Images.Thumbnails.DATA ) );

BitmapFactory.decode.....

}


3. 일반 이미지 파일에서 썸네일 추출하기

ExifInterface exif = new ExifInterface(pictureFile.getPath());

byte[] imageData=exif.getThumbnail();

Bitmap  thumbnail= BitmapFactory.decodeByteArray(imageData,0,imageData.length);



출처: http://stackoverflow.com/questions/5548645/get-thumbnail-uri-path-of-the-image-stored-in-sd-card-android

카톡의 대화입력 창 처럼 자동으로 늘어나도록 하고싶어서 검색을 하는데 대부분이 커스텀 EditText 클래스를 만들어 xml에서 사용하는 것이었다.


하지만 난 순수한 xml로만 하고싶어서 계속 찾던중에 다음과 같이 xml로만 가능한 방법을 찾았다.

maxHeight는 textSize의 크기에 맞춰서 변경해야 하며, 나는 4줄만 표시되도록 설정한 크기가 84dp이다.


android:layout_height="wrap_content" android:isScrollContainer="true" android:maxHeight="84dp" android:textSize="17.6sp"android:inputType="textMultiLine"

출처: https://snipt.net/orastem/android-multiline-edittext-that-dynamically-increases-height-to-always-display-whole-text/


사용자가 설치한 앱만 가능


adb shell "run-as {패키지명} chmod 666 /data/data/{패키지명}/databases/data.db"

adb pull /data/data/{패키지명}/databases/data.db


'develop > android' 카테고리의 다른 글

썸네일 이미지 가져오기  (0) 2016.01.08
EditText 높이 자동조절  (1) 2015.12.24
ImageButton enable 설정  (0) 2015.12.15
Screen On/Off 이벤트 받기  (2) 2015.10.29
webview youtube 백그라운드 재생 정책위반 해결  (1) 2015.10.23

ImageButton은 Layout xml에서는 enable속성을 설정할 수 없다.


오로지 ImageButton.setEnabled() API로만 설정이 가능하다.

슬립모드에 들어갈때와, 슬립모드 해제할때에 무언가 동작을 하기 위해서는 2가지 이벤트를 받아야 한다.


android.intent.action.SCREEN_ON

android.intent.action.SCREEN_OFF


이 두가지 이벤트는 안드로이드 정책 변경으로 인해 Manifest에 기술해서는 받을 수 없고, registerReceiver()를 이용하여 동적으로 등록해야만 정상적으로 이벤트를 받을 수 있다.


다음처럼 등록을 하여 사용하였다.


ScreenOnReceiver screenOnReceiver = new ScreenOnReceiver();

IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SCREEN_ON");
filter.addAction("android.intent.action.SCREEN_OFF");
registerReceiver(screenOnReceiver, filter);


class ScreenOnReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d("SmartPortal", "ScreenOnReceiver, onReceive:" + action);
        if (action.equals(Intent.ACTION_SCREEN_ON)) {
            ...
        }
        else if (action.equals(Intent.ACTION_SCREEN_OFF)) {

...

        }
    }
}



어플 등록중 구글 플레이스토어에서 정책 위반이라면서 다음과 같은 메일이 왔다.


아래 설명된 문제를 해결한 다음 변경한 업데이트를 제출하시기 바랍니다.

거부 이유: 콘텐츠 정책의 금지 사항 조항 위반

정기 검토 결과 앱에서 YouTube 동영상의 백그라운드 재생을 허용하는 것으로 확인되었으며, 이는 YouTube API 서비스 약관의 다음 부분을 위반하는 것입니다.

'귀하의 API 클라이언트 및 귀하는 사용자 또는 기타 제3자에게 다음 작업을 장려하거나 이를 가능하게 하는 기능을 만들어서는 안 됩니다. (8) YouTube API를 통해 이용하도록 제작된 모든 YouTube의 시청각 콘텐츠의 오디오 또는 동영상 요소를 구분, 분리, 수정하는 작업'


기존에 개발 된 어플을 수정만하고 있던차라 처음에는 full wake lock을 하는 서비스 때문에 문제가 있는거라 생각하여 쓸모없는 서비스라 제거를 하고 다시 시도를 했지만 2번째엔 앱이 삭제되었다고 메일이 왔다. 정책 위반사항은 위의 빨간색으로 표시한 것과 같은 내용이었다.


어플이 실제로는 webview를 통해서 모바일페이지를 보여주는 형태의 껍데기이기 때문에 계속 찾다보니 회사 사이트에서 youtube 사이트로 가는 링크가 있는것을 알게되었고, 거기서 영상을 재생하고 슬립모드로 들어가도 영상이 계속 재생(소리가 계속 재생됨)되는것을 확인하였다.


기본 인터넷 어플은 전혀 그런현상이 없는것을 확인하고 이리저리 알아본 결과 다음과 같이 해결할 수 있었다. webview가 있는 activity의 onPause를 추가한다.


protected void onPause() {
    super.onPause();
    try {
        Class.forName("android.webkit.WebView")
            .getMethod("onPause", (Class[]) null)
            .invoke(webView, (Object[]) null);
    } catch(Exception e) {
        e.printStackTrace();
    }
}


WebView.onPause()도 있으나 이 API는 Android 11에서부터 지원한다.


이제 영상은 정상적으로 pause되나 웹뷰 동작이 정상적이지 않게된다. 그것은 onResume을 호출해줌으로써 해결했다.




2017.1.10 추가

protected void onResume() {
    super.onResume();
    try {
        Class.forName("android.webkit.WebView")
            .getMethod("onResume", (Class[]) null)
            .invoke(webView, (Object[]) null);
    } catch(Exception e) {
        e.printStackTrace();
    }
}






퍼옴: http://www.kaisyu.com/notes/google-android/android-partial-module-build


특정 모듈만 build 하기

  • $ANDROID_HOME/build/envsetup.sh 스크립트를 사용하면 간편하게 특정 module만 build할 수 있다. (envsetup.sh에 대한 더 상세한 내용은여기를 참고하자.)
  • 먼저 shell 상에서 위 스크립트를 현재 환경으로 load 해준다. ($ANDROID_HOME 환경 변수는 Android full source root 경로 값을 저장하고 있는 것으로 미리 정의되어 있어야 한다.)
    $ . $ANDROID_HOME/build/envsetup.sh
  • 자주 사용한다면 그냥 .profile 이나 .bashrc 같은 파일에 추가해두는 것도 좋다.
  • 아무튼, 위 스크립트에서 제공하는 함수들 중 m, mm, mmm 세 가지를 사용하게 된다.
    • m - 현재 경로를 기준으로 소스 트리의 최상위 경로로 이동한 후 make를 실행해준다.
    • mm - 현재 경로를 기준으로 가장 가까운 단위 모듈을 찾아서 그 모듈만 build 해준다.
    • mmm - 파라미터로 주어진 경로들에 대해 단위 모듈 build를 해준다. 마지막에 snod를 추가할 경우 System image 파일까지 새로 생성해준다.
  • 예를 들어보자.
    • Email application package만 새로 build 하고 싶은 경우 다음과 같이 해줄 수 있다.
      $ cd $ANDROID_HOME/packages/apps/Email
      $ mm
    • 혹은 mmm을 사용해서 package build 후 System image까지 새로 생성하는 방법도 있다.
      $ cd $ANDROID_HOME/packages/apps/Email
      $ mmm . snod


TCP hole punching 모듈이 있어서 테스트 하려고 다운받으니 jar로 되어 있다.


홈페이지에서 하라는대로 다 하고 android에서 실행하려니 Exception 발생


03-27 16:10:46.123: E/AndroidRuntime(16929): FATAL EXCEPTION: main

03-27 16:10:46.123: E/AndroidRuntime(16929): java.lang.ExceptionInInitializerError

03-27 16:10:46.123: E/AndroidRuntime(16929): at com.ahope.test_tcp_hole.MainActivity.onClick(MainActivity.java:34)

03-27 16:10:46.123: E/AndroidRuntime(16929): at android.view.View.performClick(View.java:4114)

03-27 16:10:46.123: E/AndroidRuntime(16929): at android.view.View$PerformClick.run(View.java:17097)

03-27 16:10:46.123: E/AndroidRuntime(16929): at android.os.Handler.handleCallback(Handler.java:615)

03-27 16:10:46.123: E/AndroidRuntime(16929): at android.os.Handler.dispatchMessage(Handler.java:92)

03-27 16:10:46.123: E/AndroidRuntime(16929): at android.os.Looper.loop(Looper.java:137)

03-27 16:10:46.123: E/AndroidRuntime(16929): at android.app.ActivityThread.main(ActivityThread.java:4885)

03-27 16:10:46.123: E/AndroidRuntime(16929): at java.lang.reflect.Method.invokeNative(Native Method)

03-27 16:10:46.123: E/AndroidRuntime(16929): at java.lang.reflect.Method.invoke(Method.java:511)

03-27 16:10:46.123: E/AndroidRuntime(16929): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)

03-27 16:10:46.123: E/AndroidRuntime(16929): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)

03-27 16:10:46.123: E/AndroidRuntime(16929): at dalvik.system.NativeStart.main(Native Method)

03-27 16:10:46.123: E/AndroidRuntime(16929): Caused by: java.lang.ExceptionInInitializerError

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:242)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:254)

03-27 16:10:46.123: E/AndroidRuntime(16929): at de.htwg_konstanz.in.uce.hp.parallel.target.HolePunchingTarget.<clinit>(HolePunchingTarget.java:51)

03-27 16:10:46.123: E/AndroidRuntime(16929): ... 12 more

03-27 16:10:46.123: E/AndroidRuntime(16929): Caused by: java.lang.VerifyError: org/apache/log4j/config/PropertySetter

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:772)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:735)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:615)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:502)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:547)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:483)

03-27 16:10:46.123: E/AndroidRuntime(16929): at org.apache.log4j.LogManager.<clinit>(LogManager.java:127)

03-27 16:10:46.123: E/AndroidRuntime(16929): ... 16 more


apache의 log4j를 android에서 사용할 수 없다는 것인데...


찾아보니 android에서 직접 사용하는것에 대한 예제와 해결방법은 많은데 내가 원하는것은 없었다..



java 소스를 git로 받아서 로그 출력하는 부분을 주석처리 할까 하다가, jar에 있는 class파일을 변경하면 되지 않을까란 생각이 들었다.


http://www.slf4j.org/download.html 사이트에서 수정된 jar파일을 받아 class파일을 원래 jar에 적용하니 잘 작동한다.








예를들어 자바 클래스 A가 있고 아래와 같은 정의가 있을 때
A.java
class A {
int aa;
byte [] bb;
static {loadlibrary(...);}
native void func();
}

native.cpp
JNIEXPORT void JNICALL func(JNIEnv *e, jobject self)
{
jclass cls = e->GetObjectClass(self);
jfieldID aaId = e->GetFieldID(cls, "aa", "I");
jfieldID bbId = e->GetFieldID(cls, "bb", "[B");

jint aa = e->GetObjectField(self, aaId);
jbytearray bb = e->GetObjectField(self, bbId);
....
}

만약 String 변수를 사용하는경우

jstring str = e->GetObjectField(self, fid); const char * pcName = _env->GetStringUTFChars(jstr, NULL); strcpy(user.caName, pcName); e->ReleaseStringUTFChars(jstr, pcName); // ReleaseStringUTFChars 반드시 해준다.



밑의 표는 GetFieldID 의 3번째 인자에 넣을 값이다.

Type Signature

Java Type

Z

boolean

B

byte

C

char

S

short

I

int

J

long

F

float

D

double

L fully-qualified-class ;

fully-qualified-class

[ type

type[]

( arg-types ) ret-type

method type




A라는 Activity에서 화면 회전등의 변경이 일어날 때 메모리에 저장된 데이터를 유지하기 위하여 Manifest에서 해당 Activity에 다음과 같은 속성을 설정했다.


android:configChanges="orientation"


기본적으로 이 설정은 잘 동작하지만, 보통 추천하는 설정은 다음과 같다.


android:configChanges="orientation|keyboardHidden"


GB 소스를 참고해서 만들고 있었기 때문에 몰랐었던 내용이었는데, 위 설정에도 불구하고 JB MR2에서 onConfigurationChanged() 가 호출되지 않고 onSavedIns...() -> onDestroy() -> onCreate() 과정의 메서드가 호출이 되었다.


안드로이드 개발 사이트를 뒤적여보니 다음과 같은 내용이 있었다. (출처 : http://developer.android.com/guide/topics/resources/runtime-changes.html)


Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersionattributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must decalare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).


최종적으로 다음과 같이 설정하니 잘 동작한다.


android:configChanges="orientation|keyboardHidden|screenSize"


+ Recent posts