펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


Uri uri = Uri.fromParts("package", "패키지명", null);

Intent delIntent = new Intent(Intent.ACTION_DELETE, uri);

startActivity(delIntent);


메소드를 하나 만들어서 패키지명을 인자로 넘겨받으면


입력값으로 넘어온 패키지를 삭제할 수 있다.


바로 삭제가 되는것이 아니라, 삭제가 가능한 화면을 띄워주는것이다.


어플단에서 바로 삭제처리하는것은 일반적으로 불가능하다고 보면 된다.



설치된 패키지 정보를 보는 방법은 이전 포스팅을 보면 된다.



펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO




웹뷰(Javascript)와 안드로이드간 메소드를 호출하려고 하는데 ,


안드로이드 > 자바스크립트로는 메소드 호출이 되지만


자바스크립트 > 안드로이드로는 메소드 호출이 안되는 경우가 있다.



오늘 이 현상때문에 개고생을 하다가 결국 원인을 찾아냈다.



수없이 올라오는 로그를 자세히 보니 웹뷰에서 안드로이드의 메소드를 호출 할 때


Writing exception to parcel

java.lang.SecurityException: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL

at com.android.server.am.ActivityManagerService.handleIncomingUser(ActivityManagerService.java:13192)

at android.app.ActivityManager.handleIncomingUser(ActivityManager.java:2044)

at com.android.providers.settings.SettingsProvider.callFromPackage(SettingsProvider.java:615)

at android.content.ContentProvider$Transport.call(ContentProvider.java:279)

at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:273)

at android.os.Binder.execTransact(Binder.java:388)

at dalvik.system.NativeStart.run(Native Method)



이런 에러코드가 발생한다는걸 알았고,


소스코드를 아무리 변경해봐도 안되고, 퍼미션에 찾아봐도 저런 퍼미션은 없었다.


원인은 AndroidManifest.xml 파일의 android:targetSdkVersion="18" 이 문제였다.


웹뷰 > 안드로이드는 4.2버전부터 호출이 막혔다고 한다.


(http://ttorr.blogspot.kr/2014/03/kitkat44-loadurl.html)



android:targetSdkVersion16 이하로 설정하거나, 아예 없어버린 뒤 해결되었다.


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


14/10/14 추가 : import android.webkit.JavascriptInterface; + 메소드에 @JavascriptInterface 어노테이션을 추가하면 api level 17 이상에서도 작동한다.

(http://stackoverflow.com/questions/16353430/appview-addjavascriptinterface-does-not-work-on-api-17)


펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO





Handlermsgint값을 보낼 수 있다는것은 알것이다.

(http://biig.tistory.com/34  -  핸들러 사용법 포스팅)



그렇다면, 메시지로 객체를 전달할 수는 없을까 ??


할 수 있다.


기존에는


handler.sendEmptyMessage(int);


형식으로 메시지를 전송했다면,



같은 위치에서


Message msg = handler.obtainMessage();


으로 선언 해 주면


msg.what(int);

msg.obj(Object);

msg.arg1(int);

msg.arg2(int);


이런식으로 메시지에 객체를 담을 수 도 있고, 인트값도 저렇게 넣어 줄 수 있다.


잘 활용한다면 매우 유용하다.


예를들어 다른 액티비티에 객체를 전달해야 하는 경우, parcelable를 상속받고 기타 과정이 복잡한데


Handler를 통해 Object를 넘겨주면 매우 간단하게 해결이 가능하다.


그리고 sendEmptyMessage 대신


handler.sendMessage(msg);


로 해주면 전달이 완료된다.




펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO




Ctrl + Shift + O

ㄴ 자동 import. import가 필요한 부분은 자동으로 연결 해 주고, 불필요한 import는 제거한다.

    초보의 경우, 빨간줄이 생기면 한번씩 눌러보면 해결되는 경우가 많다.


Ctrl + M

ㄴ 현재 활성화 돼 있는 창 이외의 모든 창을 최소화. 즉 소스코드창이 활성화 돼 있는 상태라면,

    소스코드 창을 제외한 Project창이나 Console창이 최소화돼 소스코드창을 넓게 사용 가능.

    한번 더 누르면 원래상태로 복귀한다.


Ctrl + D

ㄴ 커서 라인을 삭제한다.


Ctrl + Shift + C  == Ctrl + /

ㄴ 선택 영역 또는 현재 라인을 주석처리한다. (한손으로 가능해서 편함)


Ctrl + Alt + 방향키 Up , Down

ㄴ 포커스가 위치한 라인을 위 또는 아래에 그대로 Copy 한다.


Ctrl + F

Find/Replace창 표시


Ctrl + Z , Ctrl + Y

Z는 작업 이전으로, YZ로 뒤로갔던것을 다시 앞으로 돌린다.


Ctrl + W

ㄴ 현재 활성화 된 탭 닫기


Ctrl + S

ㄴ 수정사항 저장


Ctrl + L

ㄴ 라인을 입력하는 창이 나오고, 라인을 입력하면 해당 라인으로 이동


F3

ㄴ 메소드/변수를 블록선택 하고 F3을 누르면 해당 메소드가 선언된곳으로 이동한다.


Ctrl + K, Ctrl + Shift + K

ㄴ 메소드/변수를 블록선택하고 단축키를 실행하면 선택된 메소드의 사용한 이전, 다음 사용 라인으로 이동한다.


Ctrl + Shift + F

ㄴ 선택된 영역 코딩스타일 자동 정렬




Android/View | Posted by 덩치 2014. 4. 15. 10:55

간단한 얼럿다이얼로그 출력

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO




AlertDialog.Builder builder = new AlertDialog.Builder(mContext)

.setTitle("종료")

.setMessage("프로그램을 종료 하시겠습니까?")

.setPositiveButton("예", new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dlg, int value) {

finish();

}

})

.setNegativeButton("아니요", null);

AlertDialog dialog = builder.create() ;

dialog.show() ;



아니오 버튼에도 리스너를 등록하고싶으면 예 처럼 다이얼로그인터페이스의 클릭리스너를 등록 해 주면 된다.


빌더 옵션에 .addView(view) 를 하면 LayoutInflater로 가져온 뷰를 내용에 셋팅할 수 있다.

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO




private void getPackageList() {

PackageManager pm = this.getPackageManager();


List<PackageInfo> packs =                   getPackageManager().getInstalledPackages(PackageManager.PERMISSION_GRANTED);

Log.i("TAG", "===================================================");

for (PackageInfo pack : packs) {

Log.d("TAG", "| name    : " + pack.packageName);

      Log.d("TAG", "| package : " + pack.packageName);

      Log.d("TAG", "| version : " + pack.versionName);

}

Log.i("TAG", "===================================================");

}



휴대폰에 설치 된 패키지명과 어플명, 버전을 가져온다.



public void onRemovePackage(String removePackage) {

Uri uri = Uri.fromParts("package", removePackage, null);

Intent intent = new Intent(Intent.ACTION_DELETE, uri);

startActivity(intent);

}


removePackage로 받아 온 패키지명의 어플을 삭제하겠냐는 팝업이 나타나고, 해당 패키지를 삭제한다.


호출은 


onRemovePAckage("com.example.test");




Android/View | Posted by 덩치 2014. 4. 9. 16:13

WebView를 이용해 javascript와 통신하기

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


시작하기 전 주의점 : 빌드타겟 ~16 에서는 정상적으로 작동,

타겟 17이상부터는 호출되는 메소드에 @JavascriptInterface 어노테이션을 반드시 추가 해 주어야함


WebView로 띄운 페이지와 App간에 메시지를 주고 받는 방법에 대해 알아보자.


우선 웹뷰를 생성한다.

WebView mWebView ;

mWebView = (WebView) findViewById(R.id.webview);


그리고  웹뷰의 세팅을 자바스크립트를 사용가능하도록 선언한다 (default : false)

mWebView.getSettings().setJavaScriptEnabled(true);


그리고 자바스크립트로부터 데이터를 전달받을 클래스를 생성 해 준다.


private class AndroidBridge {

    public void setMessage(final String arg) {

    handler.post(new Runnable() {

    public void run() {

    mTextView.setText("받은 메시지 : \n" + arg);

    }

    });

    }

    }


자바스크립트에서 AndroidBridge라는 클래스로 메시지를 보내 줄 수 있게 하기 위해서 다음과 같이 선언한다.

mWebView.addJavascriptInterface(new AndroidBridge(), "android");

이제 자바스크립트에서는 AndroidBridge()에 "android"라는 이름으로 접근할 수 있게 되었다.


그리고 웹뷰에 표시할 url을 셋팅 해 준다.

mWebView.loadUrl("file:///android_asset/javapage.html");


자바스크립트 파일 : 

본인은 프로젝트의 assets 폴더javapage.html 이라는 로컬파일을 만들어서 넣고 해당 경로를 선언했다.

첨부 : 

javapage.html

파일 안의 내용은

<html>

<head>

<script language="JavaScript">

function setMessage(arg) {

 document.getElementById('textMessageFromApp').innerHTML = arg;

function sendMessage(msg){

window.android.setMessage(msg);

}

</script>

<style>

input {

position:absolute; top:100%; margin-top:-80px;

}

</style>

</head>

<body>

<hr/>

<h2>WebView와의 통신</h2>

<hr/>

<br/>

받은 메시지 :

<p id="textMessageFromApp" style="height:200px; overflow-y:auto;"> 

</p>

<hr/>

<input type="text" id="textMessageToApp"  value="App으로 전송"/>

<input type="button" value="Send Message" onclick="sendMessage(document.getElementById('textMessageToApp').value)" style="left:50%;"/>

</body>

</html>


중요한부분은 녹색으로 표시 했고,

자세한건 나머지 소스를 보면서 설명하겠다.


App - > 자바스크립트로 메시지 전달 :


아래 소스코드는 에디트텍스트에 적은 내용을 웹뷰로 날려주는것인데, 버튼클릭리스너 등에서 사용한다.

mWebView.loadUrl("javascript:setMessage('" + mEditText.getText() + "')");


이렇게 메시지를(mEditText.getText() 를 javascript:setMessage( ); 에 날려주게되면,

javapage.html 파일의 setMessage 부분에 arg로 값이 전달된다.


html파일에서는 arg로 값을 받아서 textMessageFromApp이라는 텍스트뷰에 표시해 주고 있다.


자바스크립트 - > App으로 메시지 전달 :

페이지의 버튼을 클릭하면 onclick 안의 내용이 실행되면서 textMessageToApp 텍스트뷰의 내용이

sendMessage를 통해 전달된다. sendMessage 부분을 보면


window.android.setMessage(msg);

이렇게 돼 있는데, 아까전에 위에서

mWebView.addJavascriptInterface(new AndroidBridge(), "android");

라고 인터페이스를 추가한 것을 기억해 보면 초록색 소스코드가 이해될것이다.

자바스크립트에서 android라는 이름으로 setMessage를 해 주는 것이다.


이렇게 되면 안드로이드의 AndroidBridge클래스에서 메시지를 받아서 텍스트뷰의 내용을

자바스크립트에서 보낸 msg로 출력된다.



이상으로 안드로이드와 자바스크립트간의 양방향 메시지 전달 방법에 대해 알아보았다.


예제 프로젝트 :

WebView_Javascript.zip


(참조 : http://blog.daum.net/kwh4865/13153880)




펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


패키지명을 입력하면 설치 여부를 알려주는 소스코드


PackageInfo pi;  

try {

String strAppPackage = "패키지명 (ex : com.exam.googlemap)";

pi = getPackageManager().getPackageInfo(strAppPackage,  PackageManager.GET_ACTIVITIES);

}

catch (PackageManager.NameNotFoundException e) {

//패키지가 설치되지 않음

}


버전을 구하고싶다면


String str = pi.versionName;




Android/소스코드 | Posted by 덩치 2014. 3. 26. 13:21

화면캡쳐 방지 소스코드

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

어플 화면이 캡쳐되지 않도록 해달라는 요청을 받고 검색하다가 발견한 소스코드.


불가능할줄 알았는데 api level 1부터 이런게 있었다니 .. 충격


getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);


정확한 원리는 모르겠는데 몇몇 기종으로 테스트 해 본 결과


어떤 폰에서는 캡쳐기능을 사용할 수 없습니다 라는 토스트를 출력하고


어떤 폰에서는 캡쳐 직전 바로 검은 화면을 띄워서 해당 화면이 캡쳐되도록 하는 듯 하다.



위 코드 한줄만 넣어주면 적용 완료.


특정 영역에서만 캡쳐를 방지하고싶다면, 이외의 영역에는

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);

를 추가하면 된다.


참고로 액티비티가 액티브되고 있는 상태에서만 적용. 즉 홈화면으로 나가서 캡쳐를하면 제대로 캡쳐가 된다.


펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



startActivity(new Intent(android.provider.Settings."액션"));


한줄만 넣어주면 원하는 설정창을 띄워줄 수 있다.


예를들어 GPS설정창을 띄우고 싶은 경우


startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));


데이터네트워크 설정창을 띄우고 싶은 경우


startActivity(new Intent(android.provider.Settings.ACTION_DATA_ROAMING_SETTINGS));



이외에도 Settings 하위에 액션들이 많으니 필요한 액션을 찾아서 적용시켜주면 유용하게 쓰일듯 하다.