원격 호출은 C#이나 자바에서도 찾아 볼 수 있다. 이는 클라이언트를 위한 기능 제공으로 자신의 기능을 메서드로 노출시켜 호출함으로 서비스를 이용한다. 다른 OS들의 COM에 대한 개념이라 생각하면 될 듯하다.

이 역시 Service 클래스를 상속받아 사용한다.

데몬에서는 onStartCommand를 이용하여 실행 했다면 여기에서는 onBind를 이용하여 사용하며, onCreate에서는 최소한의 초기화만 하면 되고 나머지는 onBind를 구현하여 처리를 한다.

이를 코딩 할 경우 aidl 확장자 안에 인터페이스를 구현하여 컴파일러가 자바 파일을 생성한다. 이 위치는 gen폴더 아래에 보면 알 수 있을 것이다.

다음은 인터페이스를 확장하여 작성한 코드이다.

public class CalcService extends Service {
 public void onCreate() {
  super.onCreate();
 }
 
 public void onDestroy() {
  super.onDestroy();
 }

 public IBinder onBind(Intent intent) {
  return mBinder;
 }
 
 ICalc.Stub mBinder = new ICalc.Stub() {
  public int getLCM(int a, int b) throws RemoteException {
   int i;
   for (i = 1; ;i++) {
    if (i % a == 0 && i % b == 0) break;
   }
   return i;
  }

  public boolean isPrime(int n) throws RemoteException {
   int i;
   for (i = 2;i < n; i++) {
    if (n % i == 0) return false;
   }
   return true;
  }
 };
}

여기에서 보면 ICalc.Stub 타입의 객체를 생성하여 그 안에 해당하는 내용을 작성한 것을 볼 수가 있다.

다음은 이를 제어하는 코드이다.

public class CalcClient extends Activity {
 ICalc mCalc;
 TextView mResult;
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.service_calcclient);
  
  mResult = (TextView)findViewById(R.id.result);
  
  Button btnLCM = (Button)findViewById(R.id.btnLCM);
  btnLCM.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    int LCM = 0;
    try {
     LCM = mCalc.getLCM(6, 8);
    } catch (RemoteException e) {
     e.printStackTrace();
    }
    mResult.setText("6과 8의 최소 공배수 = " + LCM);
   }
  });

  Button btnPrime = (Button)findViewById(R.id.btnPrime);
  btnPrime.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    boolean prime = false;
    try {
     prime = mCalc.isPrime(7);
    } catch (RemoteException e) {
     e.printStackTrace();
    }
    mResult.setText("7의 소수 여부 = " + prime);
   }
  });
 }
 
 public void onResume() {
  super.onResume();
  Intent intent = new Intent(this, CalcService.class);
  bindService(intent, srvConn, BIND_AUTO_CREATE);
 } 

 public void onPause() {
  super.onPause();       
  unbindService(srvConn);
 }

 ServiceConnection srvConn = new ServiceConnection() {
  public void onServiceConnected(ComponentName className, IBinder binder) {
   mCalc = ICalc.Stub.asInterface(binder);
  }

  public void onServiceDisconnected(ComponentName className) {
   mCalc = null;
  }
 };
}

위에서 보면 ServiceConnection 객체를 생성하고 서비스의 연결과 종료 됨을 구현 한 것을 볼 수가 있다.

bindService의 인자 값인 BIND_AUTO_CREATE 은 자동으로 서비스를 동작 시키는 것이다.

또한 데몬의 예제 처럼 매니페스트 상에 이름을 지정 한 경우,

onResume의 내용은 다음과 같고,

super.onResume();
Intent intent = new Intent("서비스 액션 이름");
bindService(intnet,srvConn,BIND_AUTO_CREATE);

ServiceConnection의 onServiceConnected 구현의 내용은 다음과같다.

mCalc = 패키지명.ICalc.Stub.asInterface(binder);

[Android] Demon Android 2012. 3. 12. 17:08

데몬, 보이지 않는 곳에서 작업을 하는 프로세스이다. 이는 안드로이드의 서비스 컴포넌트 내에 해당하는 것이다.

이는 onCreate에 의해 생성이 되고 onStartCommnd에 의해 실행, onDestory에 의해 생명 주기가 완료된다.

다음은 그 예제이다.

public class ImageViewActivity extends Service {
 boolean mQuit;

 public void onCreate() {
  super.onCreate();
 }
 
 public void onDestroy() {
  super.onDestroy();

  Toast.makeText(this, "Service End", 0).show();
  mQuit = true;
 }

 public int onStartCommand (Intent intent, int flags, int startId) {
  super.onStartCommand(intent, flags, startId);

  mQuit = false;
  NewsThread thread = new NewsThread(this, mHandler);
  thread.start();
  return START_STICKY;
 }

 public IBinder onBind(Intent intent) {
  return null;
 }
 
 class NewsThread extends Thread {
  ImageViewActivity mParent;
  Handler mHandler;
  String[] arNews = {    "1",    "2",    "3",    "4"  };
  public NewsThread(ImageViewActivity parent, Handler handler) {
   mParent = parent;
   mHandler = handler;
  }
  public void run() {
   for (int idx = 0;mQuit == false;idx++) {
    Message msg = new Message();
    msg.what = 0;
    msg.obj = arNews[idx % arNews.length];
    mHandler.sendMessage(msg);
    try { Thread.sleep(5000);} catch (Exception e) { ; }
   }
  }
 }

 Handler mHandler = new Handler() {
  public void handleMessage(Message msg) {
   if (msg.what == 0) {
    String news = (String)msg.obj;
    Toast.makeText(ImageViewActivity.this, news, 0).show();
   }
  }
 };
}

여기서 하나 더 추가 할 것이 매니페스트에 존대한다. service 부분이다.

<service android:name=".check">
        <intent-filter>
            <action android:name=".demon" />
        </intent-filter>
</service>

위와 같이 꼭 서비스를 등록하고 사용 할 경우에는 Intent를 생성 할 경우 인자 값으로 해당하는 Intent의 이름을 넣어주고 하면 된다.

아래 코드는 그것과 달리 Intent에서 해당 클래스를 바로 불러와서 실행하는 코드이다.

public class ImageViewActivity extends Activity {
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.test);
  
  Button btnstart = (Button)findViewById(R.id.start);
  btnstart.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    Intent intent = new Intent(NewsController.this, NewsService.class);
    startService(intent);
   }
  });

  Button btnend = (Button)findViewById(R.id.end);
  btnend.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    Intent intent = new Intent(NewsController.this, NewsService.class);
    stopService(intent);
   }
  });
 }
}
위에서 보면 이들 서비스는 startService와 stopService에 의해 작동 됨을 확인 할 수가 있다.

[Android] 배터리 Android 2012. 3. 12. 16:50

배터리에 조사에 대한 샘플이다. 필요하면 찾아 쓰면 좋을 듯 하다.

public class ImageViewActivity extends Activity {
 TextView mStatus;

 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  mStatus = (TextView)findViewById(R.id.result);
 }
 
 public void onResume() {
  super.onResume();
  IntentFilter filter = new IntentFilter();
  filter.addAction(Intent.ACTION_BATTERY_CHANGED);
  filter.addAction(Intent.ACTION_BATTERY_LOW);
  filter.addAction(Intent.ACTION_BATTERY_OKAY);
  filter.addAction(Intent.ACTION_POWER_CONNECTED);
  filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
  registerReceiver(mBRBattery, filter);
 } 

 public void onPause() {
  super.onPause();       
  unregisterReceiver(mBRBattery);
 }

 BroadcastReceiver mBRBattery = new BroadcastReceiver() {
  int Count = 0;
  public void onReceive(Context context, Intent intent) {
   String action = intent.getAction();
   Count++;
   //배터리 충전 상태 변경, registerReceiver 메서드로 명시적으로 등록해야함
   if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
    onBatteryChanged(intent);
   }
   if (action.equals(Intent.ACTION_BATTERY_LOW)) {
    Toast.makeText(context, "배터리 위험 수준", Toast.LENGTH_LONG).show();
   }
   if (action.equals(Intent.ACTION_BATTERY_OKAY)) {
    Toast.makeText(context, "배터리 양호", Toast.LENGTH_LONG).show();
   }
   if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
    Toast.makeText(context, "전원 연결됨", Toast.LENGTH_LONG).show();
   }
   if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
    Toast.makeText(context, "전원 분리됨", Toast.LENGTH_LONG).show();
   }
  }

  public void onBatteryChanged(Intent intent) {
   int plug, status, scale, level, ratio;
   String sPlug = "";
   String sStatus = "";

   //배터리 존재 여부 확인
   if (intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false) == false){
    mStatus.setText("배터리 없음");
    return;
   }

   //외부 전원 연결되어 있는지 확인, 0이면 배터리 연결, BATTERY_PLUGGED_AC면 어댑터, USB면 USB에 연결 상태
   plug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
   status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
     BatteryManager.BATTERY_STATUS_UNKNOWN);
   scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);//배터리 레벨 최대량
   level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);//현재 충전 레벨
   //EXTRA_HEALTH 성능 상태, EXTRA_ICON_SMALL 배터리 상태 아이콘 리소스 아이디
   //EXTRA_TECHNOLOHY 배터리 방식 조사, EXTRA_TEMPERATURE 온도 조사, EXTRA_VOLTAGE 전압 조사
   ratio = level * 100 / scale;
   
   switch (plug) {
   case BatteryManager.BATTERY_PLUGGED_AC:
    sPlug = "AC";
    break;
   case BatteryManager.BATTERY_PLUGGED_USB:
    sPlug = "USB";
    break;
   default:
    sPlug = "Battery";
    break;
   }

   switch (status) {
   case BatteryManager.BATTERY_STATUS_CHARGING:
    sStatus = "충전중";
    break;
   case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
    sStatus = "충전중 아님";
    break;
   case BatteryManager.BATTERY_STATUS_DISCHARGING:
    sStatus = "방전중";
    break;
   case BatteryManager.BATTERY_STATUS_FULL:
    sStatus = "만충전";
    break;
   default:
   case BatteryManager.BATTERY_STATUS_UNKNOWN:
    sStatus = "알 수가 없어";
    break;
   }

   String str = String.format("수신 회수:%d\n연결: %s\n상태:%s\n레벨:%d%%",
     Count, sPlug, sStatus, ratio);
   mStatus.setText(str);
  }
 };
}

[Android] BR Android 2012. 3. 12. 16:29

브로드 캐스트 즉, 방송을 뜻한다. 이는 BroadcastReceiver 클래스에 상속받아 onReceive(Context,Intent) 를 호출하여 실행된다.

이들은 메인 스레드에 의해 실행 됨으로 10초의 시간 내에 접속이 되지 않으면 정지하는 습성을 지니고 있다.

방송 시작에 대해서는 sendBroadcast(Intent,String)과 sendOrderedBroadcast(Intent, String) 두가지 방법으로 호출이 된다.

다음은 샘플 예제이다.

public class ImageViewActivity extends Activity {
 static final int NAPNOTI = 1;
    NotificationManager mNotiManager;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        Button btn = (Button)findViewById(R.id.call);
        btn.setOnClickListener(new Button.OnClickListener() {
         public void onClick(View v) {
          Intent intent = new Intent();
          intent.setAction("imageview.test.BroadCast");
          sendBroadcast(intent);
         }
        });       
    }
}

public class check extends BroadcastReceiver {
   
    public void onReceive(Context context, Intent intent) {
     Intent intent2 = new Intent(context, DownHtml.class);
     intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     context.startActivity(intent2);
    }
}

위에서 보면 setAction이 있음을 확인 할 수 있을 것이다. 이는 매니페스트 파일 내의

<receiver android:name=".check">
        <intent-filter>
            <action android:name="imageview.test.BroadCast" />
        </intent-filter>
</receiver>
이와같은 부분을 추가 해 주면 된다.

이와 다르게 BroadcastReceiver 자체를 새로 생성해서 처리 할 수 있다.

액티비티를 상속받은 클래스 내에 이를 생성하고 그 아래 onReceive를 구현 해 주면 된다.

여기에서 하나 더 보태자면 onResume과 onPause를 구현해야하는데

onResume내에 들어 갈 코드는 다음과 같다.

super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("필터 이름");
registerReceiver(BroadcastReceiver);

onPause내에 들어 갈 코드는 다음과 같다.
super.Pause();
unregisterReceiver(BroadcastReceiver);

[Android] 통지 Android 2012. 3. 12. 15:35

통지는 다들 아실 것이다. 문자가 날아온다던지 뭐 이것 저것 알릴 때 이용된다.

샘플은 다음과 같다.

public class ImageViewActivity extends Activity {
 static final int NAPNOTI = 1;
    NotificationManager mNotiManager;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        Button btn = (Button)findViewById(R.id.call);
        btn.setOnClickListener(new Button.OnClickListener() {
         public void onClick(View v) {
          Toast.makeText(ImageViewActivity.this, "눌러보세요", 0).show();
          v.postDelayed(new Runnable() {
     public void run() {
         Notification noti = new Notification(R.drawable.ic_launcher,
           "확인하세요",System.currentTimeMillis());
         noti.defaults |= Notification.DEFAULT_SOUND;
         // 진동 사용
         //noti.defaults |= (Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
         // 커스텀 진동
         //noti.vibrate = new long[] {1000,1000,500,500,200,200,200,200,200,200};
         noti.flags |= Notification.FLAG_INSISTENT;
         
         Intent intent = new Intent(ImageViewActivity.this, check.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         PendingIntent content = PendingIntent.getActivity(
           ImageViewActivity.this, 0, intent, 0);
         noti.setLatestEventInfo(ImageViewActivity.this, "확인",
           "확인했음?", content);
         NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
         manager.notify(1, noti);
     }
          }, 5 * 1000);
         }
        });       
    }
}

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        NotificationManager mNotiManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        mNotiManager.cancel(ImageViewActivity.NAPNOTI);
        Button btn = (Button)findViewById(R.id.call1);
        btn.setOnClickListener(new Button.OnClickListener() {
         public void onClick(View v) {
          finish();
        }});       
    }

여기에서 보면 알림 매니저에 의해 등록되고 인텐드 한 것이 호출 됨을 알 수 있다. 하지만 호출 할 때 매니페스트에 반드시 호출 할 대상을 지정 해 두는 것을 잊지 말자.



[Android] JSON Parser Android 2012. 3. 8. 16:54

JSON은 XML 보다 좀 더 간략화 된 데이터의 구성이다. 이는 단순한 유니코드 텍스트 파일로 가독성이 좀 떨어지나 어느 환경이든 적용이 가능하다.

또한 파서 자체가 라이브러리 형태로 제공되어 직접 문자열을 파싱 할 필요가 없다.

JSON에 저장되는 정보 형태는 배열과 객체, 단순 값으로 된다.

다음 코드는 배열과 객체를 파싱하여 이용하는 코드 이다.

먼저 배열의 경우이다.

public class ImageViewActivity extends Activity {
 EditText edit;

 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Button call = (Button) findViewById(R.id.call);
  edit = (EditText) findViewById(R.id.edit);
  call.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    String str = "[1,2,3,4,5]";
    try{
     int sum=0;
     JSONArray ja = new JSONArray(str);
     for(int i=0;i<ja.length();i++){
      sum+=ja.getInt(i);
     }
     edit.setText("total" + sum);
    }
    catch(JSONException ex){
     Toast.makeText(v.getContext(), ex.getMessage(), 0).show();
    }
   }
  });
 }
}

위에서 봤듯 Array에 넣어 해당하는 타입으로 가져와 데이터를 조작 할 수가 있다. 다음은 객체형이다.

onClick 내의 내용을 다음과 같이 바꾸기만 하면 된다.

String str = "[{\"one1\":\"1\", \"one2\":\"11\", \"one3\":\"111\"},{\"one1\":\"2\", \"one2\":\"22\", \"one3\":\"222\"}]";
    String temp = "";
    try{
     JSONArray ja = new JSONArray(str);
     for(int i=0;i<ja.length();i++){
      JSONObject obj = ja.getJSONObject(i);
      temp += obj.getString("one1")+obj.getString("one2")+obj.getString("one3")+"\n";
     }
     edit.setText(temp);
    }
    catch(JSONException ex){
     Toast.makeText(v.getContext(), ex.getMessage(), 0).show();
    }

객체형은 getJSONObject에서 가져와 각기 데이터를 추출한다. 여기에서 배열 형태로 저장된 규칙을 잘 지키기만 하면 된다.

[Android] XML Parser Android 2012. 3. 8. 16:25

XML에는 크게 DOM과 SAX 파서가 존재한다.

DOM은 트리 형식으로 문서를 읽으면서 전체 구조 파악 후 정보를 구하고 SAX는 순차적으로 문서를 읽으면서 정보를 차례대로 읽는 방식이다.

다음이 그 예제이다.

public class ImageViewActivity extends Activity{ 
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  Button call = (Button)findViewById(R.id.call);
  call.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<order><item>unit</item>"+
    "<item one=\"one1\" two=\"two2\">first</item>"+
    "<item one=\"one2\" two=\"two2\">second</item>"+
    "</order>";    
    try{
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//자체가 추상 클래스임으로 빌더 객체를 얻고 난 다음 메서드로 문서를 파싱하면 Document 객체가 생성이 됨.
     DocumentBuilder builder = factory.newDocumentBuilder();
     InputStream stream = new ByteArrayInputStream(xml.getBytes("utf-8"));
     Document doc = builder.parse(stream);
     org.w3c.dom.Element order = doc.getDocumentElement();//루트 엘리먼트 가져옴
     NodeList items = order.getElementsByTagName("item");
     //한줄의 간단 경우
     //Node item = items.item(0);
     //Node text = item.getFirstChild();
     //다수의 아이템 경우
     String result = "";
     for(int i=0;i<items.getLength();i++){
      Node item = items.item(i);
      Node text = item.getFirstChild();//노드 탐색하는 형태 지정 함
      String name = text.getNodeValue();//getNodeName과 getNodeType을 이용하여 이름과 타입도 가져옴
      result+=name+" --- ";
      NamedNodeMap attrs = item.getAttributes();//속성 값을 가져오기 위함
      for(int j=0;j<attrs.getLength();j++){
       Node attr = attrs.item(j);
       result+=attr.getNodeName()+"="+attr.getNodeValue();
      }
      result+="\n";
     }
     EditText edit = (EditText)findViewById(R.id.edit);
     edit.setText(result);
    }
    catch(Exception ex){
     Toast.makeText(v.getContext(), ex.getMessage(), 0).show();
    }
   }
  });
 }
}

DOM은 속도가 빠르며 임의 노드를 여러번 읽지만 최초 시작이 조금 느리면서 문서 크기에 따라 메모리에 대한 부하가 커진다. 반면 SAX는 메모리를 거의 사용하지 않으며 최초 실행이 빠르다. 하지만 읽기만을 담당한다.

public class ImageViewActivity extends Activity {
 EditText edit;

 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Button call = (Button) findViewById(R.id.call);// ��
  edit = (EditText) findViewById(R.id.edit);
  call.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    edit.setText("Test");
    String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
      + "<order><item>sss</item></order>";
    try {
     SAXParserFactory factory = SAXParserFactory.newInstance();
     SAXParser parser = factory.newSAXParser();
     XMLReader reader = parser.getXMLReader();
     SaxHandler handler = new SaxHandler();
     reader.setContentHandler(handler);
     InputStream stream = new ByteArrayInputStream(xml
       .getBytes("utf-8"));
     reader.parse(new InputSource(stream));
     
     edit.setText(handler.sb.toString());
    } catch (Exception ex) {
     Toast.makeText(v.getContext(), ex.getMessage(), 0).show();
    }
   }
  });
 }

 class SaxHandler extends DefaultHandler {
  boolean flag = false;
  StringBuilder sb = new StringBuilder();

  public void startDocument() {
  }

  public void endDocument() {
  }

 

  @Override
  public void startElement(String uri, String localName, String qName,
    org.xml.sax.Attributes attributes) throws SAXException {
   // TODO Auto-generated method stub
   Log.d("DATA", "startElement");
   // @Override
   if (localName.equals("item")) {
    flag = true;
   }
  }
  public void endElement(String uri, String localName, String qName) {
  }
  
  @Override
  public void characters(char[] chars, int start, int length) {
   // @Override
   Log.d("DATA", "startElement");
   if (flag) {
    sb.append(chars, start, length);
    flag = false;
   }
  }
 };
}

그 외에 XmlPullParser 라는 것이 있다. 이는 SAX와 유사하나 이벤트 발생시마다 핸들러 대신 루프 돌면서 이벤트를 직접 조사한다.

예제는 다음과 같다.

public class ImageViewActivity extends Activity {
 EditText edit;

 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Button call = (Button) findViewById(R.id.call);
  edit = (EditText) findViewById(R.id.edit);
  call.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    edit.setText("Test");
    String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
      + "<order><item>sss</item></order>";
    boolean flag = false;
    String name = "";
    try {
     XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
     XmlPullParser parser = factory.newPullParser();
     parser.setInput(new StringReader(xml));
     
     int type = parser.getEventType();
     while(type!=XmlPullParser.END_DOCUMENT){
      switch(type){
      case XmlPullParser.START_DOCUMENT : break;
      case XmlPullParser.END_DOCUMENT : break;
      case XmlPullParser.START_TAG :
       if(parser.getName().equals("item")){
        flag = true;
       }
      case XmlPullParser.END_TAG : break;
      case XmlPullParser.TEXT :
       if(flag){
        name = parser.getText();
        flag = false;
       }
       break;
      }
      type = parser.next();
     }
     edit.setText(name);
    } catch (Exception ex) {
     Toast.makeText(v.getContext(), ex.getMessage(), 0).show();
    }
   }
  });
 }

 class SaxHandler extends DefaultHandler {
  boolean flag = false;
  StringBuilder sb = new StringBuilder();

  public void startDocument() {
  }

  public void endDocument() {
  }

 

  @Override
  public void startElement(String uri, String localName, String qName,
    org.xml.sax.Attributes attributes) throws SAXException {
   // TODO Auto-generated method stub
   Log.d("DATA", "startElement");
   // @Override
   if (localName.equals("item")) {
    flag = true;
   }
  }
  public void endElement(String uri, String localName, String qName) {
  }
  
  @Override
  public void characters(char[] chars, int start, int length) {
   // @Override
   Log.d("DATA", "startElement");
   if (flag) {
    sb.append(chars, start, length);
    flag = false;
   }
  }
 };
}

[Android] 웹 서비스 Android 2012. 3. 8. 13:07
아래는 공개된 서비스 호출을 하여 웹서비스 처리를 한 코드이다. 응용에 대해서는 각기 해당하는 경우 찾아서 하면 될 듯 하다.

public class ImageViewActivity extends Activity{ 
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  Button call = (Button)findViewById(R.id.call);
  call.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    String xml;    
    String name = "사용자";
    int count=2;
    String url = "http://twitter.com/statuses/user_timeline.xml?screen_name="+name+"&count="+count;
    xml = DownloadHtml(url);
    EditText edit = (EditText)findViewById(R.id.edit);
    edit.setText(xml);
   }
  });
 }
 
 String DownloadHtml(String add){
  StringBuilder sb = new StringBuilder();
  try{
   URL url = new URL(add);
   HttpURLConnection connect = (HttpURLConnection)url.openConnection();
   if(connect!=null){
    connect.setConnectTimeout(1000);
    connect.setUseCaches(false);
    if(connect.getResponseCode()==HttpURLConnection.HTTP_OK){
     BufferedReader br = new BufferedReader(new InputStreamReader(connect.getInputStream()));
     for(;;){
      String line = br.readLine();
      if(line==null) break;
      sb.append(line+'\n');
     }
     br.close();
    }
    connect.disconnect();
   }
  }
  catch(Exception ex){}
  return sb.toString();
 }
}

이 코드를 실행해보면 최근 게시물 두개를 요청 한 것이다.

서버상에서 이미지를 읽어와서 이미지 뷰에 보이고 또한 다운로드 받는 예제이다.

다운받은 파일은 DDMS 상에서 확인이 가능하다.

public class ImageViewActivity extends Activity{ 
 ImageView m_imgview;
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  m_imgview = (ImageView)findViewById(R.id.img);
  Button draw_btn = (Button)findViewById(R.id.draw);
  draw_btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    String imgurl="파일경로";
    {
     InputStream is;
     try {
      is = new URL(imgurl).openStream();
      Bitmap bmp = BitmapFactory.decodeStream(is);
      m_imgview.setImageBitmap(bmp);
      is.close();
     } catch (MalformedURLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
  });
  
  Button down_btn = (Button)findViewById(R.id.down);
  down_btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    String imgurl="파일경로";    
    int index = imgurl.lastIndexOf('/');
    String localimg = imgurl.substring(index+1);
    String path = Environment.getDataDirectory().getAbsolutePath();
    path += "/data/imageview.test/"+localimg;
    if(new File(path).exists()==false){
     DownLoadImage(imgurl,localimg);
    }
    Bitmap bitmap = BitmapFactory.decodeFile(path);
    m_imgview.setImageBitmap(bitmap);
   }
  });
 }
 
 boolean DownLoadImage(String url, String filename){
  URL imgurl;
  int read;
  try{
   imgurl = new URL(url);
   HttpURLConnection connect = (HttpURLConnection)imgurl.openConnection();
   int length = connect.getContentLength();
   byte[] data = new byte[length];
   InputStream is = connect.getInputStream();
   FileOutputStream fos = openFileOutput(filename,0);
   
   for(;;){
    read = is.read(data);
    if(read<=0) break;
    fos.write(data,0,read);
   }
   is.close();
   fos.close();
   connect.disconnect();
  }
  catch(Exception ex){return false;}
  return true;
 }
}

다음 코드는 앞서 포스팅 한 것에 대한 문제를 조금 해결 한 것이다.

즉, 버튼을 다 누르면 ANR(5초 이내 응답 없을 시 경고 메세지와 함께 프로세스 종료) 상태 처럼 버튼에 색이 들어오고 난 다음 멈춰 있는 것을 방지 한 것이다.

방법은 쓰레드를 돌려서 핸들러를 호출하여 내용을 바꾼 방식이다.

public class ImageViewActivity extends Activity{
 ProgressDialog m_progress;
 Main_Thread m_thread;
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  Button btn = (Button)findViewById(R.id.dwon);
  btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    m_progress = ProgressDialog.show(ImageViewActivity.this, "Wait please", "Now Downloding");
    m_thread = new Main_Thread();
    m_thread.start();
   }
  });
 } 
 
 class Main_Thread extends Thread{
  String m_add = "http://google.com";
  String m_result = "";
  
  public void run(){
   StringBuilder sb = new StringBuilder();
   try{
    URL url = new URL(m_add);
    HttpURLConnection connect = (HttpURLConnection)url.openConnection();
    if(connect!=null){
     connect.setConnectTimeout(1000);
     connect.setUseCaches(false);
     if(connect.getResponseCode()==HttpURLConnection.HTTP_OK){
      BufferedReader br = new BufferedReader(new InputStreamReader(connect.getInputStream()));
      for(;;){
       String line = br.readLine();
       if(line==null) break;
       sb.append(line+'\n');       
      }
      br.close();
      m_result = sb.toString();
     }
     connect.disconnect();
    }
   }
   catch(Exception ex){}
   handler.sendEmptyMessage(0);
  }
 }
  
 Handler handler = new Handler(){
  public void handleMessage(Message msg){
   m_progress.dismiss();
   EditText txt = (EditText)findViewById(R.id.edit_txt);
   txt.setText(m_thread.m_result);
  }
 };
}

이 역시 아파치 라이브러리로 표현 가능하다 방법은 다음과 같다.

class Main_Thread extends Thread{
  String m_add = "http://google.com";
  String m_result = "";
  
  public void run(){
   HttpGet http = new HttpGet(m_add);
   DefaultHttpClient client = new DefaultHttpClient();
   try{
    client.execute(http,reshandler);
   }
   catch(Exception ex){}
   handler.sendEmptyMessage(0);
  }
 }
 
 ResponseHandler<String> reshandler = new ResponseHandler<String>(){
  public String handleResponse(HttpResponse response){
   StringBuilder sb = new StringBuilder();
   try{
    BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    for(;;){
     String line = br.readLine();
     if(line==null) break;
     sb.append(line+'\n');
    }
    br.close();
    Message message = handler.obtainMessage();
    Bundle bundle = new Bundle();
    bundle.putString("result", sb.toString());
    message.setData(bundle);
    handler.sendMessage(message);
   }
   catch(Exception ex){}
   return sb.toString();
  }
 };
  
 Handler handler = new Handler(){
  public void handleMessage(Message msg){
   m_progress.dismiss();
   EditText txt = (EditText)findViewById(R.id.edit_txt);
   txt.setText(msg.getData().getString("result"));
  }
 };