Android/XMPP2010. 10. 6. 16:31
Smack은 opensource로 제공되는  XMPP library이다. 안드로이드에서 사용이 가능하다.
실시간으로 XMPP server와 통신이 가능하고 인스탄트메세징과 채팅이 가능하다

아래와 같이 지극히 단순한 코드로 단문메세지를 전송할 수 있다.
XMPPConnection connection = new XMPPConnection("jabber.org");
connection.connect();
connection.login("mtucker", "password");
Chat chat = connection.getChatManager().createChat("jsmith@jivesoftware.com", new MessageListener() {

    public void processMessage(Chat chat, Message message) {
        System.out.println("Received message: " + message);
    }
});
chat.sendMessage("Howdy!"); 

프로그래머에게 패킷레벨의 접근이 필요없으며 Chat, Roater같은 상위레벨의 클래스를 사용하여 프로그래밍이 가능하다
XMPP XML format이나 XML에 대해서도 알필요가 없다.


Posted by 삼스
Android/App개발2010. 9. 28. 19:54

안드로이드에서 Push notification을 구현하기 위한 방법으로 XMPP를 이용하는 방법과 MQTT를 이용하는 방법이 있다..
여기서는 MQTT를 이용하여 C2DM을 지원하지 않는 안드로이드 2.1이하 버전에서 PUSH notification을 지원하기 위한 방법에 대해 설명한다.

안드로이드 앱에서 Push notification을 지원하기 위한 방안은 3가지정도의 방안이 있다.
1. 폴링
  이게 진정 push일까?? 어쨌든 단말에서 주기적으로 서버에 가져갈 메세지가 있는지 확인하여 push event를 수신할 수 있다. 
  장점 : 구현이 쉽고 비용도 안든다.
  단정 : 실시간이 아니지 않은가... 이런 젝일~!, 이는 배터리소모까지 발생시킨다.. 끔찍하다.이에 대한 정보는 링크를 참조하자. https://labs.ericsson.com/apis/mobile-java-push/blog/save-device-battery-mobile-java-push
2. SMS
  안드로이드는 SMS message의 가로채기가 가능하다. 서버에서 특별한 SMS를 단말에 날리면 앱에서는 모든 SMS 메세지를 가로채서 서버에서 날린것인지 확인하고 Popup Message를 띄울 수 있을것이다.
  장점 : 구현이 쉽다. 완전한 실시간이 보장된다. 알려진 솔루션도 있다. Ericsson lab의 자료를 참조하라 https://labs.ericsson.com/apis/mobile-java-push/
  단점 : 비용이 발생한다.
3. 끊김없는 TCP/IP
  폰과 서버가 TCP/IP 연결을 유지한다. 그리고 주기적으로 keepalive메세지를 날린다. 서버는 이 연결을 통해 필요할경우 메세지를 보낸다.
  장점 : 완전한 실시간이 보장된다.
  단점 : 신뢰성을 보장하는 구현이 아주 까다롭다. 폰과 서버쪽 모두 구현하려면 이야기가 복잡해진다. 또 안드로이드는 low memory등의 상황에서 서비스가 종료될 수도 있다. 그러면 동작을 안할것이다. 또한 단말이 sleep에 들어가지 않아야 하므로 유저들은 배터리문제로 클레임을 걸수 있다.

1, 2의 방법은 중대한 단점이 있다. 3번째는 가능하기는 하다. 하지만 먼가 개운치는 않다.

구글링을 통해서 몇몇 개발자들의 TCP/IP방식의 몇가지 좋은 시도를 찾았다.
Josh guilfoyle은 AlarmManager에 기반하여  오랬동안 살아있는 connection을 어떻게 만들것인가에 대해 언급했다. 그는 백그라운드에서 동작하면서 그 연결을 만들어내는 멋진 샘플코드도 제공하였다. http://devtcg.blogspot.com/2009/01/push-services-implementing-persistent.html

Dave Rea는  Deacon project를 최근에 시작했다. Meteor server상에서 comet technology를 사용하여 안드로이드에서 push notification을 지원하는 3rd party library를 개발할 예정이다. 아주 초기 단계이다.  http://deacon.daverea.com/

Dale Lane는 IBM에서 개발한 MQTT protocol로 android에서 push notification을 지원하는것과 관련한 많은 자료를 만들었으며 아주 훌룡한 샘플코드도 제공한다. http://dalelane.co.uk/blog/?p=938

위의 훌룡한 시도들을 기반으로 예제를 만들었다. 이 는 Josh Guilfoyle의 TestKeepAlive project 와 Dale Lane의 MQTT를 이용한 것이다.

TestKeepAlive project의 문제점은 raw TCP connection을 만든다는 것이다. 이는 push를 관리하는 서버를 별도로 작성해야 한다는것을 의미한다. MQTT를 이용한 예제의 경우 서버작업을 위해 IBM의 MQTT broker를 이용한다. 

mqtt는 publish/subscribe messaging protocol로 가볍게 설계 되었다. 가볍게 설계 되었다는 것은 '저전력 소모'를 지원한다는 것이다. 이는 끊김없는 TCP/IP connection을 고려해야 하는 모바일환경에서 가장 이상적인 해결책이다. 다만 MQTT의 단점은 개인의 프라이버시 보장이 약하다는 것등 몇가지 단점이 있기는 하다.

KeepAliveService와 raw TCP/IP connection을 MQTT connection으로 변경하는 것이 아이디어의 핵심이다.

Architecture
예제에서는 서버에서 PHP를 사용하였다. 이는 Simple Asynchronous Messaging library(http://project-sam.awardspace.com/)를 사용하였다.

system_diagram

wmqtt.tar 는 IBM에서 제공하는 MQTT protocol의 간단한 drop-in implementation이다.  http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006에서 다운로드 가능하다. 

Really Small Message Broker(RSMB)는 간단한 MQTT broker로 마찬가지로 IBM에서 제공한다. http://www.alphaworks.ibm.com/tech/rsmb에서 다운가능하다. 1833포트가 디폴트로 동작한다. 위 아키텍쳐에서 서버로부터 메세지를 받아서 단말에 전송하는 역할을 한다. RSMB는 Mosquitto server(http://mosquitto.atchoo.org/)로 변경이 가능하다.
SAM은 MQTT와 다른 요소들을 모아놓은 PHP library이다. http://pecl.php.net/package/sam/download/0.2.0에서 다운가능하다.

send_mqtt.php는 POST를 통해 메세지를 받아서 SAM을 이용하여 broker에 메세지를 전달하는 역할을 한다.

Sample code and Demo
push-app
이 예제는 TextView하나와 두개의 Button이 있다. 폰에 설치 후 서비스를 시작한 후 http://tokudu.com/demo/android-push/  에 가서 deviceID를 입력하고 메세지를 입력하라. 그러고 난 후 "Send Push Message"를 누르면 폰에서 메세지를 받을 것이다. 
























MQTT는 사실 안드로이드에서 Push를 지원하기 위한 최적의 방법은 아니다. 하지만 잘 동작한다. MQTT의 가장 취약한 점은 broker가 동작하는 IP와 PORT정보를 누군가 알아낸다면 모든 Push message들을 가로챌수 있다는 것이다. 따라서 그런 정보를 encrypt하는것은 좋은 대안이 될것이다. 대안으로 당신만의 broker를 작성하여 MQTT에 인증을 추가하는것이 있을 수 있다.

이 예제는 더 테스트되어야 한다. 안정성은 보장못한다. 연결이 끊어지거나 예외상황들에 대한 처리가 더 개선되어야 한다. 





Posted by 삼스
Android/App개발2010. 9. 9. 18:57
http://blog.naver.com/huewu/110083320332

안드로이드에서 Service 를 사용하는 방법에는 크게 두 가지가 있습니다.


 첫번째는 startService() / stopService() 를 이용해서, 특정 Service 를 시작 하거나 종료 시키는 것입니다. 두 번째는, bindService() 를 이용해서, Service 의 IBinder 객체를 얻어온 후, 해당 Service 에서 정의된 API 를 호출 하는 방법입니다. 

 Service 에 Bind 한 후, API 를 호출하는데는 두 가지 방법이 있습니다. Local Service 로 구현하는 방법과 Remote Service 로 구현하는 방법입니다. Local Service 의 경우에는 Service 와 Service 를 이용하는 어플리케이션이 항상 동일한 Process 에서 작동하는 경우에 해당합니다. 이 경우 bindService() 의 결과로 바로 해당 Service 에 접근해서 원하는 API 를 호출 할 수 있습니다. 하지만 실재로 Service 가 돌고 있는 Process 가 아닌 별개의 Process 에서 API 를 호출 하고자 할 때는 반드시 IBinder 와 AIDL을 통해  RPC(Remote Procedure Call)이 이루어져야 합니다. 보다 상세한 내용은 안드로이드 개발자 사이트의 AIDL 관련 항목을 참조하시면 좋습니다.

  안드로이드 SDK 중에는Remote Service Binding 관련 예제가 첨부되어 있습니다. 하지만 예제의 경우, Remote Service 와 해당 Service 를 이용하는 어플리케이션 모두 동일한 Package 에 속해 있습니다. 그런데, 제 경우에 Service 를 제작하는 개발자와 Service 를 사용하는 어플리케이션을 개발하는 개발자가 달라, 작업상의 편의를 위해 서로 다른 Package 에 속한 완전히 구분된 형태로 구현할 필요가 생겼습니다. 

 그래서 서로 다른 Package / Process 에서 작동하는 Service 와 어플리케이션을한번 만들어 보려고 했습니다만... 생각보다 수월하지 않더군요. 몇 가지 삽질 끝에, AIDL 에 관련된 클래스를 하나의 패키지로 분리한 후, JAR 라이브러리로 생성하고, Service 와 어플리케이션 모두 동일하게 해당 JAR 를 참조하면 원하는 바대로 정상적으로 동작함을 확인 할 수 있었습니다. 

<AIDL 을 위한 프로젝트를 생성하고, 원하는 Interface 를 정의해 보았습니다.>

 AIDL 패키지를 생성하고 JAR 라이브러리로 뽑는 방법은 다음과 같습니다. 우선 안드로이드 프로젝트를 생성한 후, 원하는 인터페이스를 갖는 AIDL 파일을 추가합니다. 그러면 자동적으로 AIDL 툴이 작동하고, 해당 AIDL 인터페이스에 대응되는 클래스 파일이 생성 추가됩니다. (그림의 경우, printLog() 라는 API 를 갖는 Test.aidl 을 추가 하자, 자동으로 Test.java 파일이 생성되었음을 확인 할 수 있습니다.)

<일반적인 JAR 파일로 Export 하면 됩니다.>

 그 후, 해당 프로젝트에 대하여 JAR File 로 Export 합니다. 이 때, 그림과 같이 우리에게는 AIDL 툴이 자동으로 생성해준 Java  파일내의 내용만이 필요함으로, 해당 파일 외에 다른 것들은 포함할 필요가 없습니다. 특히 AndroidMenifest 파일을 포함하게 되면, 다른 안드로이드 프로젝트에서 해당 JAR 파일을 참조할 수 없으니 (중복된 파일이 존재해서...) 주의해야 합니다. 

<생성한 JAR 파일을 프로젝트에 추가하자.>

 그 다음에는 구현하고자 하는 RemoteService 와 RemoteController 에서 해당 JAR 파일을 참조 라이브러리로 추가하면 작업 완료. 그 이 후의 방법은 일반적인 방법과 동일합니다. RemoteService 는 해당 JAR 를 참조한 후, JAR 내에 정의된 클래스를 Import 한 후, Stub 클래스를 구현하면 되고, RemoteController 에서는 bindService() 이 후에, JAR 에 정의된 대로, Stub 클래스의 asInterface() API 를 호출해서 AIDL 인터페이스 클래스를 생성한 후, 원하는 API 를 호출하면 됩니다.



 <결과가 볼품 없긴 하지만, 정상적으로 동작하고 있다...>

 그림을 유심히 살펴보시면, RemoteService 는 PID 274 인 Process 에서, RemoteController 는 PID 267인 Process 에서 작동 중이고, 로그창에서 확인 할 수 있듯이, PID 267 인 RemoteController 의 Process 가 RemoteService 의 API 를 호출 함을 확인하실 수 있습니다. 보다 상세한 구현 내용은 첨부한 압축파일을 풀어서, 세 개의 프로젝트를 살펴보시면 도움이 될 듯 합니다. (주석이 없어서 조금...애매하긴 하지만...)

 그런데 왜 이런 번거러운 작업이 필요하게 된걸까요?

 서로 다른 Package 를 사용할 때, RemoteController 는 RemoteService 에 바인드 한 후, 한 후, 자신이 Bind 한 Service 가 제공해주는 AIDL 인터페이스에 대한 정보를 알 수가 없습니다. 이 때 생각해 볼 수 있는 방안이 두 가지 있는데... 첫째는 Service 생성에 사용한 AIDL 파일을 그대로 또다른 어플리케이션에 복사해서 또 하나의 AIDL 인터페이스 클래스를 생성하는 방법이고, 두 번째는, 해당 Service 가 구현된 패키지를 참조하는 방법입니다. 두 가지 방법 모두 시도해 보았습니다만, 어플리케이션이 강제로 종료되고 말더군요. 

 우선 AIDL 을 그냥 복사하는 경우. 비록 AIDL 에 정의된 인터페이스와 자동으로 생성된 클래스의 구현 내용은 동일할지 모르지만, RemoteService 에서 사용되는 클래스와는 서로 다른 별도의 클래스가 생성되는 셈입니다. 따라서, bindService 를 통해 전달받은 IBinder 객체를 이용해서 원래 정해진 RemoteService 내에 정의된 클래스 외에 다른 클래스로 변환하고자 하니까 SecurityException 이 발생하게 됩니다.

 두 번째로, 단순히 해당 Service 를 참고만하는 경우에는 컴파일은 정상적으로 수행되긴 하지만, 실제 작동 시에 문제가 발생하게 됩니다. bindService() 를 통해 전달받은 IBinder 객체를 이용해 RemoteService 에 정의된 Proxy 객체를 생성하고자 하지만, RemoteController 패키지내에는 해당 클래스에 관한 정보가 전혀 없기 때문에, Class Definition 을 찾을 수 없다는 오류가 발생하게 됩니다. 

 저 개인적으로는 처음에, AIDL 파일만 있으면 어떤 어플리케이션이던지 손쉽게, 내가 스스로 작성한 Service 에 Bind 한 후, 원하는 API를 호출할 수 있을지 않을까 했습니다만... 세상에 쉬운일은 없더군요. 무슨일이던지 실재로 해보지 않고 마음대로 상상하지 말자...라는 걸 느끼게 해준 삽질이였습니다.
Posted by 삼스
Android/App개발2010. 9. 7. 14:56

1. jad 사용법
D:\javasrc\ojdbc14>jad -r -d src -sjava oracle\**\*.class

2. dex decompile 
 classes.dex 폴더 위치에 gen폴더 생성
 undx.jar과 AXMLPrinter2.jar파일을 classes.dex폴더 위치에 복사
 java -DASDKLoc=c:\android-sdk\tools -jar undx.jar classes.dex
   -> gen폴더에 classes.dex.dump와 classes.jar파일이 생성됨
 classes.jar파일의 압축을 해재
 jad로 class파일을 java파일로 decompile

3. AndroidManifest.xml
  java -jar AXMLPrinter2.java sourcexml.xml > targetxml.txt




Posted by 삼스
Android/App개발2010. 9. 3. 21:11
Wednesday, September 23rd, 2009 | Author: Tim
Mmmmm... Market Data...

Mmmmm... Market Data...

It turns out downloading a free application is actually pretty easy to reproduce. The things required by the google android servers are just four variables. The server needs to know your userIdauthToken,deviceId and the applications assetId.
The 
userId is a unique number that is associated only with your gmail account, the one that is currently linked to the phone. I’m working on getting a generic way to grab this number, though I believe the request is buried in an ssl request to the google servers. So for now, you can obtain your own userId by doing a tcpdump of your market traffic, just do a download of an application and look for a “GET” request in wireshark. There does not appear to be a “hard” maximum character on this, I’ve seen userIds as low as 8 in length and as high as 13. A bad userId will return a 403 forbidden response.
The 
authToken is sent in cookie form to the server, to authenticate that the user is using a valid and non-expired token and well, is who they say they are! This is linked to the userId and must match the account that the userId is taken from. Expired tokens will return a 403 forbidden response.
The 
deviceId is simply your Android_ID, and is linked in anyway to the authtoken or user-id, so feel free to spoof this.
The 
assetId is a number (negative or positive) that identifies the current stream of the application you wish to download. More on this later when I cover how to get live market data. Note that this number is not always the same - it (appears) to change when something from the application is changed. Originally I referred to this in my research as a “cacheAppID” for just that purpose.

  1. // Downloading apk's without vending/market 
  2. // Coded by Tim Strazzere 
  3. import java.io.FileNotFoundException; 
  4. import java.io.IOException; 
  5. import java.io.InputStream; 
  6. import java.io.BufferedOutputStream; 
  7. import java.io.FileOutputStream; 
  8. import java.io.UnsupportedEncodingException; 
  9. import java.net.MalformedURLException; 
  10. import java.net.URL; 
  11. import java.net.URLEncoder; 
  12. import java.net.HttpURLConnection; 
  13.  
  14. public class main { 
  15.     public static void main(String[] args) { 
  16.         // current assetId for the yahoo search apk 
  17.         String assetId = "7884814897504696499"
  18.         // input your userId 
  19.         String userId = "12345678901"
  20.         // spoof your deviceId (ANDROID_ID) here 
  21.         String deviceId = "2302DEAD532BEEF5367"
  22.  
  23.         // input your authToken here 
  24.         String authToken = "DQAAA...BLAHBLAHBLAHYOURTOKENHERE"
  25.  
  26.         String cookie = "ANDROID=" + authToken; 
  27.  
  28.         try { 
  29.             // prepare data for being 'get'ed 
  30.             String rdata = "?" + URLEncoder.encode("assetId""UTF-8") + "=" + URLEncoder.encode(assetId, "UTF-8"); 
  31.             rdata += "&" + URLEncoder.encode("userId""UTF-8") + "=" + URLEncoder.encode(userId, "UTF-8"); 
  32.             rdata += "&" + URLEncoder.encode("deviceId""UTF-8") + "=" + URLEncoder.encode(deviceId, "UTF-8"); 
  33.  
  34.             // Send data 
  35.             URL url = new URL("http://android.clients.google.com/market/download/Download" +rdata); 
  36.             HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
  37.  
  38.             // For GET only 
  39.             conn.setRequestMethod("GET"); 
  40.  
  41.             // Spoof values 
  42.             conn.setRequestProperty("User-agent""AndroidDownloadManager"); 
  43.             conn.setRequestProperty("Cookie", cookie); 
  44.  
  45.             // Read response and save file... 
  46.             InputStream inputstream =  conn.getInputStream(); 
  47.             BufferedOutputStream buffer = new BufferedOutputStream(new FileOutputStream("out.put")); 
  48.             byte byt[] = new byte[1024]; 
  49.             int i; 
  50.             for(long l = 0L; (i = inputstream.read(byt)) != -1; l += i ) 
  51.                 buffer.write(byt, 0, i); 
  52.  
  53.             inputstream.close(); 
  54.             buffer.close(); 
  55.  
  56.             System.out.println("File saved..."); 
  57.         } 
  58.         catch (FileNotFoundException e) { 
  59.             System.err.println("Bad url address!"); 
  60.         } 
  61.         catch (UnsupportedEncodingException e) { 
  62.             System.out.println(e); 
  63.         } 
  64.         catch (MalformedURLException e) { 
  65.             System.out.println(e); 
  66.         } 
  67.         catch (IOException e) { 
  68.             if(e.toString().contains("HTTP response code: 403")) 
  69.                 System.err.println("Forbidden response received!"); 
  70.             System.out.println(e); 
  71.         } 
  72.     } 

Hopefully someone will find this stuff useful ;) Better than me just sitting on it forever!

Posted by 삼스
Android/App개발2010. 9. 2. 20:48
emulator -system A:\froyo\out\target\product\generic\system.img -avd gsdk2.2
Posted by 삼스
Android2010. 8. 30. 19:48
아래 사이트에서 update가능

http://download.eclipse.org/egit/updates/


GIT repo에 접근 가능함...

Posted by 삼스
Android/App개발2010. 7. 22. 21:36
** aidl인터페이스는 말 그대로 인터페이스일 뿐이다.
** 인터페이스의 구현은 Stub 클래스를 정의하는것으로 시작된다.
ex) 
interface myInterface {
  void foo();
};

class myImplement extends myInterface.Stub {
  myImplement(Context context) {
  }
  void foo() {
  }
}

** 구현된 인터페이스를 원격에서 사용하려면 반드시 서비스를 통해서 ServiceConnection이 이루어져야 한다.
class myService extends Service {
    public final IBinder onBind(Intent intent) {
        return new myImplement((Context)this);
    }    
}

** 이렇게 하면 app단에서 bindService() 시 ServiceConnection()의 onServiceConnected()메소드를 통해 해당 인터페이스의 참조를 얻을 수 있다.
Posted by 삼스
Android/App개발2010. 7. 16. 15:42

웹페이지를 표시하는 뷰이다.

상속구조는 아래와 같다.

   ↳ android.view.View 
         ↳ android.webkit.WebView

웹브라우저에서 하는 역할을 모두 할 수 있으며 액티비티내에서 화면의 일부로 온라인컨텐츠를 표시할수 있다.
WebKin render engine을 사용하며 이전페이지, 다음페이지, 확대/축소, 텍스트검색등의 기능을 포함한다.

zoom기능을 활성화하려면 WebSettings.setBuiltInZoomControls(boolean)을 사용하라.

액티비티에서 인터넷을 억세스하고 웹페이지를 WebView에 표시하려면 아래 퍼미션을 매니페스트 파일에 추가하라.

<uses-permission android:name="android.permission.INTERNET"/>

기본적인 사용법
기본적으로 WebView는 브라우져와 유사한 위젯을 제공하지는 않는다. 자바스크립트는 비활성화되어 있으며 웹페이지에러는 무시된다. 그냥 UI의 일부로 HTML을 표시하고자 한다면 이정도면 충분하다. 만일 full-blown 웹브라우져를 원한다면 WebView를 이용하는것보다 그냥 인텐트를 날려서 브라우져에서 표시하고자 할것이다. 아래와 같이...

   Uri uri = Uri.parse("http://www.example.com");
   
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
   startActivity
(intent);
 
액티비티에서 WebView를 제공하고자 한다면 layout에 <WebView>를 추가하거나 onCreate()에서 액티비티자체를 WebView로 지정하면 된다.
   WebView webview = new WebView(this);
   setContentView
(webview);
 
이어서 원하는 웹페이지를 로드한다.

// Simplest usage: note that an exception will NOT be thrown
 
// if there is an error loading this page (see below).
 webview
.loadUrl("http://slashdot.org/");

 
// OR, you can also load from an HTML string:
 
String summary = "<html><body>You scored <b>192</b> points.</body></html>";
 webview
.loadData(summary, "text/html", "utf-8");
 
// ... although note that there are restrictions on what this HTML can do.
 
// See the JavaDocs for loadData() and loadDataWithBaseURL() for more info.

WebView는 원하는 동작을 구현하기 위해 몇가지 수정가능한 방법을 제공한다.
 - WebChromeClient의 subclass를 생성하고 설정한다. 이 클래스는 브라우져UI에서 어떤 동작이 발생하면 호출된다. 예를 들어 update과정이나 자바스크립트 경고같은 것들이 이 클래스로 전달된다.
 - WebViewClient의 서브클래스를 생성하고 설정한다. 콘텐츠의 렌더링과 연관된 동작이 발생하면 호출된다. 예를 들어 에러나 폼서브미션시(form submission)에 호출된다. shouldOverrideUrlLoading()함수를 통해 URL이 로드되기전에 원하는 작업을 할 수도 있다.
 - WebSettings의 변경가능, setJavaScriptEnabled()로 자바스크립트를 활성화할 수 있다.
 - JavaScript-to-Java 인터페이스를 추가할 수 있다. addJavascriptInterface(Object, String)메소드로 가능하다. 이 함수는 자바오브젝트를 WebView에 바인드할 수 있다. 이렇게 하여 웹페이지의 자바스크립트를 제어할 수 있다.

아래 좀더 복잡한 예제가 있다, 에러핸들링의 표시, 셋팅, 진행상태 통지등의 예를 볼수 있다.

// Let's display the progress in the activity title bar, like the
 
// browser app does.
 getWindow
().requestFeature(Window.FEATURE_PROGRESS); // 타이틀바에 진행상태 아이콘표시모드로 변경한다.

 webview
.getSettings().setJavaScriptEnabled(true); // 자바스크립트를 활성화한다.

 
final Activity activity = this;
 webview
.setWebChromeClient(new WebChromeClient() { // WebChromeClient를 설정하고 진행상태 변동상태를 화면에 반영한다.
   
public void onProgressChanged(WebView view, int progress) {
     
// Activities and WebViews measure progress with different scales.
     
// The progress meter will automatically disappear when we reach 100%
     activity
.setProgress(progress * 1000);
   
}
 
});

 webview
.setWebViewClient(new WebViewClient() { // WebViewClient를 설정하여 에러발생시 토스트로 표시한다.
   
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
     
Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
   
}
 
});

 webview
.loadUrl("http://slashdot.org/"); // 원하는 웹페이지를 연다.
 
쿠키와 윈도우관리
보안상의 이유로 당신의 애플리케이션은 자체 캐시와 쿠키 등의 저장소들을 가지고 있다. 이것은 브라우져애플리케이션의 데이터와 공유되지 않는다. 쿠키의 경우 스래드로 분리되어 관리된다. 그래서 UI thread에 의해 블럭되지 않는다. 애플리케이션에서 쿠리정보를 참조하고 싶다면 CookieSyncManager를 사용하라.

기본적으로 HTML에서 새로운 창에 여는기능은 무시된다. 이는 자바스크립트나 링크의 대상의 속성에의해 가능해진다. WebChromeClient를 수정하여 여러개의 윈도우로 페이지를 여는것을 당신 마음대로 변경할 수 있다.

액티비티의 기본동작은 configuration이 변경되면 destroy되었다가 다시 create되는것이다. 이 경우 WebView는 웹페이지를 다시 로딩하게 된다. 이게 싫다면 orientation과 keyboardHidden값을 변경하면 다시로드하지 않고 처리된다.

자주 사용된느 WebView관련 함수들
addJavascriptInterface() 자바스크립트의 자바 객체 접근 허용

createSnapshot() 현 페이지의 스크린샷 생성

getSettings() 설정을 조정하는  WebSettings 객체 반환 

loadData() 브라우저에 주어진 문자열 데이터 로딩

loadDataWithBaseURL() 기준 URL을 사용해 주어진 데이터 로딩

loadUrl() 주어진 URL을 사용해 웹페이지 로딩

setDownloadListener() 사용자가 .zip이나 .apk 파일을 다운받는 경우 등의 다운로드 이벤트의 콜백 등록

setWebChromeClient() 제목이나 진행률 표시줄을 업데이트하거나 자바스크립트 대화상자를 여등 등, WebView 영역밖에서 실행되는 이벤트의 콜백을 등록

setWebViewClient() 리소스 로딩하기, 키 눌림, 인증 요청 등의 이벤트를 방해하도록 애플리케이션이 브라우저에 걸림돌을 설정함.

stopLoading() 현재 페이지 로딩 멈추기







Posted by 삼스
Android/App개발2010. 7. 15. 13:43



개발Q&A 에 어떤분이 올리신 질문중에
"보낸이" 가 " 보냰이" 로 나온다고 하신 분이 계서서...

http://www.androidside.com/bbs/board.php?bo_table=B49&wr_id=6088&page=2

말이 나온김에 폰트에 관련된 이야기를 나누어 볼까 합니다.

먼저 폰트의 종류부터 알아보죠

비트맵 폰트 
아주 옛날^^ 8비트 컴퓨터 시절 쓰이던 폰트죠
화면에 뿌려주는 처리속도는 매우 빠르지만 글씨의 크기가 변경 될때 이쁘게 보이질 않게 되죠
이미 크기가 정해져 비트맵으로 저장 되어 있기 때문인데요
c:\windows\fonts 에 보시면


이런 폰트들이 있으실텐데요 로 표시된 폰트가 비티맵 폰트입니다.




글씨가 커질수록 안 예쁘게 보여지는 단점이 있습니다.

외곽선 폰트 
컴퓨팅 기술이 발전하면서 폰트도 이쁘게 표현할 필요가 생겼는데요
벡터 그래픽이나 베지어 곡선을 폰트에 적용하면서 외곽선 폰트 형태가 생겼습니다.
이 폰트는 크기에 상관 없이 일정한 품질의 출력을 하는 장점이 있습니다.
포스트 스크립트, 트루타입, 오픈타입 폰트등이 이에 속합니다.



포스트스크립트 (Postscript)
어도비사가 개발한 포스트스크립트 폰트는 Type1,2,3 등 다양한 포맷이 있는데요 Flash 에 적용되어
있던 벡터 개념을 폰트에도 적용하여 만든 것입니다 주로 프린터에 많이 사용됩니다.

TrueType 폰트 
베지에 3차곡선을 사용하는 Type1과는 달리 베지에 2차곡선을 사용하지만 이에대한 폰트의
품질 향상은 미비하지만 속도는 빠른 장점 때문에 windows 에서 많이 사용되고 있습니다.
위 그림중 "T" 자로 되어 있는 폰트입니다.

오픈타입 폰트 
어도비는 M$ 와 손잡고 오픈타입 폰트라는것을 제작 하게 되는데요.
true type 폰트와 postscript 폰트를 합친 새로운 형식입니다.
유니코드에 바탕을둔 truetype 에 opentype 공통의 헤더 정보를 더하여 확장시킨 포멧입니다.
유니코드이기 때문에 안드로이드에서 이 폰트를 사용하고 있습니다.
위 그림중 "O" 자로 되어 있는 폰트입니다.


서론이 너무 길었나요?
그럼 먼저 안드로이드 기본폰트에 대해 알아보죠

1. 기본폰트 사용하기




안드로이드 기본 폰트는 위 그림과 같이 
Sans , Serif  두 종류가 있구요 mono 는 각 글자의 넓이가 일정한 폰트입니다. 

layout 파일에


typeface="sans"  또는 "serif"
하시면 끝

2. 사용자폰트 사용하기


위에서 말씀드린바와 같이 windwos\fonts 에서 "O" 형태의 폰트를 고르신 후



assets\fonts\ 에 붙여넣기 합니다.

Activity onCreate 부분에 



와 같이 하시면 됩니다.

실행 화면을 볼까요?





위 화면을 보신분 중 이러한 궁금증이 생기시는분이 분명 생기실껍니다.

"그럼 폰트를 일괄 적용은 못하나요?"

그래서 말씀 드리려구요.


3. Application 전체에 특정폰트 적용하기


res/values/styles.xml 에 위 내용을 입력합니다.





메니페스트 파일에 android:theme="@style/CustomTheme" 를 추가합니다.


"그러면.. Application 전체에 커스텀폰트를 적용하려면 어떻게 하나요?"

제가 알고 있는바에 따르면 현재 버전에선 불가능 한것으로 알고 있습니다. ^^;
(완전 불가능한건 아니죠 안드로이드 core 소스를 구해서
특정폰트로 교체한 후 빌드 하면 될테니까요)
Posted by 삼스