[Android] WebView 연습

WebViewTestActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;

public class WebViewTestActivity extends Activity {
 private WebView mWebView;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
  mWebView = (WebView) findViewById(R.id.webview);
  mWebView.getSettings().setJavaScriptEnabled(true);  // 웹뷰에서 자바스크립트실행가능
  mWebView.loadUrl("http://www.google.com");    // 구글홈페이지 지정
  mWebView.setWebViewClient(new WebViewClient());  // WebViewClient 지정         
    }

 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {

  if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
 
        return super.onKeyDown(keyCode, event);
 }  
}
WebViewClient.java
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class WebViewClient extends WebViewClient {

 @Override
 public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        Log.e("shouldOverrideUrlLoading >>> ", url+"");
        return true;

 }

 @Override
 public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
  super.doUpdateVisitedHistory(view, url, isReload);
  Log.e("doUpdateVisitedHistory >>> ", url+"");
 }

 @Override
 public void onLoadResource(WebView view, String url) {
  super.onLoadResource(view, url);
  Log.e("onLoadResource >>> ", url+"");
 }
}
웹뷰에 웹페이지를 출력하는 방법과 링크를 클릭했을때 링크경로를 캐치하여 어떠한 처리를 수행할 수 있는 방법에 대해 포스팅한다. 'WebViewTestActivity.java'가 메인액티비티이며, 'WebViewClient.java'가 이러한 처리를 수행하는 클래스이다. 물론 레이아웃에는 아래처럼 선언되어 있을테고...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    />
</LinearLayout>
레이아웃은 심플하다.
구글 페이지가 열리게되면, 'shouldOverrideUrlLoading()' 메서드가 호출되고
뒤이어 'doUpdateVisitedHistory()' 메서드가 호출된다. 어떠한 링크를 클릭하여 클릭한 내역을 히스토리에 남기는 시점에 'doUpdateVisitedHistory()'이 호출되는데, 특정경로가 요청된 시점을 캐치하고 싶다면, 이 메서드내에서 url값을 파싱하여 해결할 수 있다.

예를들면, 어떠한 처리를 끝내고 특정 액티비티로 이동하고 싶다거나 할때 사용할 수 있을 것 같다.

'onLoadResource()' 메서드는 어떤놈인가 궁금해서 사용해보았는데, 그냥 이름 그대로 리소스관련 처리를 할때 사용되더라. 이미지 뿐 아니라 다양한 타입의 데이터를 요청할때에 로그가 찍히는것을 확인할 수 있다.
Log.d()를 사용하지 않고, Log.e()를 사용했는지 궁금해하시는분들은 ... 그냥 내맘이다 -_- 빨간색이 좋을뿐이다.

이밖에도 다양한 오버라이딩 메서드가 존재하더라.
각각 사용해보는것도 나쁘진 않겠지만 'onTooManyRedirects()' 같은 메서드들은 ... 상황에 맞게 테스트해야 할 것 같다. 웹뷰사용할때에 매니페스트에 권한 넣어주는거 잊지말기!

[Android] 코드에서 EditText의 inputType을 password로 지정하기!!

layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
 <EditText
  android:id="@+id/test"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text=""
     android:inputType=""
     />
</LinearLayout>
MainActivity.java
package com.vartist;

import android.app.Activity;
import android.os.Bundle;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.widget.EditText;

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        EditText myEditText = (EditText) findViewById(R.id.test);
        myEditText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
        myEditText.setTransformationMethod(new PasswordTransformationMethod());
    }
}
저도 몰랐는데, 볼드체 적용된 코드중에 두번째 라인을 적용해주지 않으면 패스워드타입이 적용되지 않는군요.

[Android] 로그캣(logcat) 한글출력

이클립스에서 사용하는 LogCat에서는 한글이 깨져서 나온다. (윈도우 버젼 이클립스. 현재 사용중인 버젼은 갈릴레오) 인코딩 문제 때문이라고 하는데 이를 cmd 콘솔에서 볼 수 있는 방법이 있다. 아래와 같이 하면 이클립스 및 해당 콘솔창에서 동시에 로그가 출력된다.

1. Win + R / cmd
2. cmd /u
3. chcp 65001
4. 콘솔창의 속성에서 폰트,를 Lucida Console 로 변경해준다.
5. adb logcat


이렇게 하면 콘솔창에 이클립스에서와 동일한 LogCat 메시지가 출력된다. 한글은 깨지지 않지만 좀 불편하긴 하다;;;;




원문 : http://globalhost.interdol.com/330

[Android] Custom ProgressBar - 프로그래스바 모양 변경

가로 프로그래스바가 아니라 싸이클 프로그래스바 수정 방법입니다.
가로 프로그래스바프로그래스바 자료는 많은데 로딩용 프로그래스바 수정 자료는 정말 없더군요.
결국 이것저것이것저것 짜 맞추다보니 해결했네요.. 뜨아~~

일단 View 용 xmlxml 입니다. 별다른게 없습니다.
1.<?xml version="1.0" encoding="utf-8"?>
2.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3.    android:orientation="vertical"
4.    android:layout_width="fill_parent"
5.    android:layout_height="fill_parent"
6.    >
7.<ProgressBar android:id="@+id/ProgressBar01" android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:indeterminateDrawable="@drawable/progress_large"/>
8.</LinearLayout>


 
기 억해두실건 android:indeterminateDrawable 속성입니다.
이 속성에 drawable 에 있는 progress_lageprogress_lage 를 넣었습니다. 이 progress_lage 또한 xml 파일입니다.
01.<?xml version="1.0" encoding="utf-8"?>
02.<!--
03./*
04.**
05.** Copyright 2009, The Android Open Source Project
06.**
07.** Licensed under the Apache License, Version 2.0 (the "License");
08.** you may not use this file except in compliance with the License.
09.** You may obtain a copy of the License at
10.**
11.**     http://www.apache.org/licenses/LICENSE-2.0
12.**
13.** Unless required by applicable law or agreed to in writing, software
14.** distributed under the License is distributed on an "AS IS" BASIS,
15.** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16.** See the License for the specific language governing permissions and
17.** limitations under the License.
18.*/
19.-->
20.<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
21.    android:drawable="@drawable/spinner_white_76"
22.    android:pivotX="50%"
23.    android:pivotY="50%"
24.     />
바 로 progress_lage.xml 은 animated-rotate 라는 태그를 보시면보시면 알듯이 회전 애니메이션에 대한 정의가 되어 있습니다. 다른건 별로 중요하지 않지만않지만 android:drawable="@drawable/spinner_white_76" 는 중요하죠.

바로바로 drawable 에 있는 spinner_white_76.png 파일을 사용하겠다라는 말입니다.
progress_lage.xmlprogress_lage.xml 은 drawable 폴더에 존재해야 하며 png 파일은 drawable-hdpi 에 존재하면 됩니다.됩니다. 그럼 저 png 파일이 빙글 빙글 돌아요~~

사용자 정의 로딩바 끝~~

사용자 삽입 이미지

 원문 : http://sync-pro.textcube.com/14

[Android] BroadcastReceiver 샘플테스트

나도 최근에 테스트해본 것이지만, 안드로이드에는 브로드캐스트 리시버라는 놈이 있다.
이놈을 간단히 설명하자면, 사용자 또는 주변환경에 의해 단말기의 상태가 변경되어 버릴때 호출되도록 미리 설정을 해 놓으면 그러한 상황이 벌어졌을때에 자동으로 (세상에 자동은 없다. 미리 설정되어 있을뿐...) 호출되는 모 그런놈이란다.

이 브로드캐스트 리시버라는 놈은 두가지 방법으로 설정해줄 수가 있다. 한가지는 XML로 매니페스트 파일에 설정을 하는것이고, 다른 하나는 자바 코드로 클래스상에서 등록해주는 것이다. 두가지 방법에는 큰 차이점이 있었다.

일단 매니페스트에 등록할때의 방법을 살펴보자.

<receiver android:name=".SampleBroadcastReceiver">
      <intent-filter>
              <action android:name="android.net.conn.CONNECTIVITY_CHANGE">
      </intent-filter>
</receiver>
인터넷에 자료가 많지만, 요놈을 매니페스트의 어느 위치에 설정하는지 나와있는 자료는 좀 드물다. 다들 잘 아는걸까 -_-; 그렇다. 나만 잘 모르는것이다. 나같은 분들은 그냥 <application></application> 사이에 다른 액티비티 설정부분과 동일한 위치에 설정을 해주면 된다.
그러면 코드로 등록하는 방법도 알아봐야겠다.

         ... (생략) ...            

    final String CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE";

    private BroadcastReceiver receiver;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        /** 네트워크 상태 표시 */
        IntentFilter filter = new IntentFilter(CONNECTIVITY_CHANGE);
        receiver = new ULNetworkReceiver(this);
        registerReceiver(receiver, filter);

    }
         ... (생략) ...
캐치하고자 하는 단말기의 상태변경항목을 이용해 필터를 생성해주고, 새로운 리시버를 생성한뒤 Activity 클래스의 registerReceiver() 메서드를 이용해서 등록한다. 등록은 이렇게 하고... 그럼 해제해주는 메서드도 있을까? 정답은 있다. 그것도 매우 쉽게 unregisterReceiver(receiver) 라는 메서드로 존재한다.

그런데 매니페스트에 설정하는 방법과 코드로 구현하는 방법에는 약간의 차이점이 있다.
코 드를 통해 프로그래밍적으로 등록된 브로드캐스트 리시버는, 브로드캐스트 리시버에 등록된 애플리케이션 컴포넌트가 실행 중인 경우에만 브로드캐스트 인텐트에 반응한다... 라고 참고된 서적에 나와있다. 매우 중요한 차이점이라 생각된다.

샘플코드를 한번 살펴보자.
매우 간단히 만들어본 코드로서, 구성은 메인액티비티와 브로드캐스트 리시버 클래스 이렇게 두개의 클래스로 존재한다. 구현내용은 메인 액티비티가 화면에 출력되면 브로드캐스트 리시버가 등록되겠지? 물론 난 코드로 구현했으니깐 항상 메인 액티비티가 보여질때만 리시버가 동작을 할거고... 화면상에는 버튼이 하나 있고, 텍스트뷰로 카운터가 있어. 그냥 버튼 누르면 카운트가 1씩 증가되는 아주 심플한 프로그램인데, 뭘 할거냐면...

네트워크 상태를 체크하는 브로드캐스트 리시버를 코드로 등록했다.
애뮬레이터 혹은 단말기로 테스트를 하는데, 애뮬레이터에서는 F8 키를 이용/단말에서는 알아서 네트워크 상태를 변경한다. 이 때에 등록된 리시버가 정상적으로 동작하고, 또 리시버가 동작할때마다 리시버클래스는 메인 액티비티의 onResume() 메서드를 호출한다. 뭐 onResume() 메서드가 하는 일은 버튼을 눌렀을때와 마찬가지로 카운트를 1씩 증가시켜 주는 역할을 한다.

더 간단히 말하자면, 브로드캐스트 리시버가 동작할때 화면상의 어떠한 액션을 줄수 있는지 테스트한 결과물이다.
너무 간만에 직접 내용을 적었더니 손가락이 아프다. 이상 끝.

0002


MainActivity.java

package com.vartist;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.vartist.receiver.ULNetworkReceiver;

public class MainActivity extends Activity {

 final String CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE";
 
 private TextView myTextView;
 private Button myUpdateButton;
 private int count = 0;
 private BroadcastReceiver receiver;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        /** 레이아웃 가져오기 */
        this.myTextView = (TextView) findViewById(R.id.myId);
        this.myUpdateButton = (Button) findViewById(R.id.updateButton);
      
        /** 네트워크 상태 표시 */
        IntentFilter filter = new IntentFilter(CONNECTIVITY_CHANGE);
        receiver = new ULNetworkReceiver(this);
        registerReceiver(receiver, filter);
      
        /** 테스트 클릭이벤트 */
        this.myUpdateButton.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    onResume();
   }
        
        });
    }

 @Override
 public void onResume() {
  super.onResume();
 
  this.myTextView.setText("테스트 어플리케이션... / count : " + this.count++);
 }

 @Override
 protected void onDestroy(){
  super.onDestroy();
  unregisterReceiver(receiver);
  Log.e("info >>> ", "unregisterReceiver()...");
 }
}
ULNetworkReceiver.java

package com.vartist.receiver;

import com.vartist.MainActivity;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;

public class ULNetworkReceiver extends BroadcastReceiver {
 
 private Activity activity;
 
 public ULNetworkReceiver() {
  super();
 }

 public ULNetworkReceiver(Activity activity) {
  this.activity = activity;
 }
 
 @Override
 public void onReceive(Context context, Intent intent) {
 
  String action = intent.getAction();
 
  // 네트웍에 변경이 일어났을때 발생하는 부분
  if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
   try {
    ConnectivityManager connectivityManager =
           (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
    NetworkInfo _wifi_network =
            connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

    if(_wifi_network != null) {
   
     /** 3G, WIFI 둘 중 하나라도 있을 경우 */
     if(_wifi_network != null && activeNetInfo != null){
      Toast.makeText(context, "상태1 : " + activeNetInfo.getTypeName(), Toast.LENGTH_SHORT).show();
     }
     /** 3G, WIFI 둘 다 없을 경우 */
     else{
      Toast.makeText(context, "상태2 : 3G/WIFI 불가능", Toast.LENGTH_SHORT).show();
     }
    
     /** 테스트용 */
     if(this.activity instanceof MainActivity) {
      ((MainActivity)this.activity).onResume();     
     }
    }
   } catch (Exception e) {
    Log.i("ULNetworkReceiver", e.getMessage());
   }  
  }
 }
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.vartist"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".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>

<!--
  <receiver android:name=".receiver.ULNetworkReceiver"
                             android:enabled="true" android:priority="0">
         <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
         </intent-filter>
  </receiver>
 -->
 
    </application>
    <uses-sdk android:minSdkVersion="7" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.INTERNET" />
</manifest>