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



public Boolean isServiceRunning(String serviceName) {

ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);

for (RunningServiceInfo runningServiceInfo :                                                   activityManager.getRunningServices(Integer.MAX_VALUE)) {

if (serviceName.equals(runningServiceInfo.service.getClassName())) {

return true;

   }

}

return false;

}


serviceName : 매니패스트에서 설정한 서비스의 이름.


ex ) <service android:name="com.biig.tistory.service.BiigService" >

에서 String serviceName = "com.biig.tistory.service.BiigService";



Android/기본스킬 | Posted by 덩치 2014. 6. 24. 17:49

LocationManager로 위치값 받아오기

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


LocationManager를 사용하기 위한 퍼미션 ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION 


모바일의 Gps 또는 Network 정보로 위치좌표를 받아오는 방법에 대해 알아보겠다.


LocationManager mLM = (LocationManager) getSystemService(Context.LOCATION_SERVICE);


이렇게 로케이션 매니저를 선언 한 뒤, 위치값 갱신을 호출 해 보자.


위치 제공자는 총 2가지 종류가 있다.


1. GPS_PROVIDER

2. NETWORK_PROVIDER


실내에서는 GPS_PROVIDER를 호출해도 응답이 없다. 응답을 기다리는 형태로 코딩을 했다면


별다른 처리를 하지 않으면 실내에서는 무한정 대기한다.


따라서 타이머를 설정하여 GPS_PROVIDER를 호출 한 뒤 일정 시간이 지나도 응답이 없을 경우


NETWORK_PROVIDER를 호출 하거나,


또는 둘 다 한꺼번에 호출하여 들어오는 값을 사용하는 방식으로 코딩을 하는것이 일반적이겠다.


private void registerLocationUpdates() {

        mLM.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,

1000, 1, mLocationListener);

mLM.requestLocationUpdates(LocationManager.GPS_PROVIDER,

1000, 1, mLocationListener);

//1000은 1초마다, 1은 1미터마다 해당 값을 갱신한다는 뜻으로, 딜레이마다 호출하기도 하지만

//위치값을 판별하여 일정 미터단위 움직임이 발생 했을 때에도 리스너를 호출 할 수 있다.

}



private final LocationListener mLocationListener = new LocationListener() {

public void onLocationChanged(Location location) {

//여기서 위치값이 갱신되면 이벤트가 발생한다.

//값은 Location 형태로 리턴되며 좌표 출력 방법은 다음과 같다.


    if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) {

//Gps 위치제공자에 의한 위치변화. 오차범위가 좁다.

double longitude = location.getLongitude();    //경도

double latitude = location.getLatitude();         //위도

float accuracy = location.getAccuracy();        //신뢰도

    }

    else {

//Network 위치제공자에 의한 위치변화

//Network 위치는 Gps에 비해 정확도가 많이 떨어진다.

    }

   }

public void onProviderDisabled(String provider) {

}


public void onProviderEnabled(String provider) {

}


public void onStatusChanged(String provider, int status, Bundle extras) {

}

}


위와같이 사용하면 된다. 그리고 더이상 위치값을 호출하지 않아도 되는 경우에는

mLM.removeUpdates(mLocationListener);자원해제를 반드시 해 준다. 누락하면 딜레이마다 계속 호출한다.





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


GoogleMap gmap =  ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map)).getMap();


gmap.setOnCameraChangeListener(new OnCameraChangeListener() {

@Override

public void onCameraChange(CameraPosition arg0) {

LatLng location_center = arg0.target;

}

});



이외에도 

double latitude = arg0.target.latitude;

double longitude = arg0.target.latitude;

또는

double latitude = location.latitude;

double longitude = location.longitude;


등으로 추출


이벤트 발생 시기는 맵이 처음 로딩됬을때와, 지도를 움직이다가 정지상태로 들어가게되면

(손가락으로 드래그하다가 멈췄을 때)


리스터가 동작하여 멈췄을때 맵의 중앙 좌표를 가져온다.

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


현재 단말기의 전화번호를 가져오고자 할때 사용한다. 

     ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number()


그리고 아래는 단말기와 관련된 내용

 

  1. AndroidManifest.xml 에 아래 권한 추가
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />

  2. 아래와 같이 Context.getSystemService 를 통해 TelephonyManager 를 가져옴.
       TelephonyManager telephony = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
        
  3. TelephonyManager 의 메소드 들 중, getLine1Number() 메소드가 전화번호를 반환
       String  telPhoneNo = telephony.getLine1Number();  

 

   출처 ( http://icess.egloos.com/3279459 )     





그리고 아래는 좀 더 많은 내용. 
분명 필요한 순간이 있을것이다. 잘 기억해두자.
=========================================================================================

android.telephony 패키지의 TelephonyManager클래스에서 담당한다.

단말기의 모뎀상태에 대한 정보를 얻기 위해서는 READ_PHONE_STATE권한이 필요하다.
AndroidManifest.xml파일에 아래 내용을 추가한다.
<uses-permission 
android:name="android.permission.READ_PHONE_STATE">
</uses-permission>

◆ 단말기의 모뎀상태 조회
TelephonyManager 객체를 얻기 위해서는 Context 객체에서 제공하는 getSystemService() 메서드를 이용한다.
TelephonyManager tm = (TelephonyManager)  
getSystemService(TELEPHONY_SERVICE);

음성통화 상태 조회
CALL_STATE_IDLE/CALL_STATE_OFFHOOK/CALL_STATE_RINGING 등의 값을 반환
Log.d("PHONE", "getCallState :" + tm.getCallState());
데이터통신 상태 조회
DATA_DISCONNECTED/DATA_CONNECTING/DATA_CONNECTED/DATA_SUSPENDED 등의 값을 반환
Log.d("PHONE", "getDataState :" + tm.getDataState());
단말기 ID 조회
GSM방식 IMEI 또는 CDMA방식의 MEID 값을 반환
Log.d("PHONE", "getDeviceId :" + tm.getDeviceId());
SW버전 조회
GSM방식의 IMEI/SV와 같은 SW버전을 반환
Log.d("PHONE", "getDeviceSoftwareVersion :" + tm.getDeviceSoftwareVersion());
전화번호 조회
GSM방식의 MSISDN과 같은 전화번호 반환
Log.d("PHONE", "getLine1Number :" + tm.getLine1Number());
국가코드 조회
현재 등록된 망 사업자의 MCC(Mobile Country Code)에 대한 ISO 국가코드 반환
Log.d("PHONE", "getNETWORKCountryIso :" + tm.getNetworkCountryIso());
Log.d("PHONE", "getSimCountryIso :" + tm.getSimCountryIso());
망 사업자코드 조회
현재 등록된 망 사업자의 MCC+MNC(Mobile Network Code) 반환
Log.d("PHONE", "getNetworkOperator :" + tm.getNetworkOperator());
Log.d("PHONE", "getSimOperator :" + tm.getSimOperator());
망 사업자명 조회
현재 등록된 망 사업자명 반환
Log.d("PHONE", "getNetworkOperatorName :" + tm.getNetworkOperatorName());
Log.d("PHONE", "getSimOperatorName :" + tm.getSimOperatorName());
망 시스템 방식 조회
현재 단말기에서 사용중인 망 시스템 방식을 반환
NETWORK_TYPE_UNKNOWN/
GSM방식 :  NETWORK_TYPE_GPRS/NETWORK_TYPE_EDGE/NETWORK_TYPE_UMTS/
NETWORK_TYPE_HSDPA/NETWORK_TYPE_HSUPA/NETWORK_TYPE_HSPA
CDMA방식 : NETWORK_TYPE_CDMA/NETWORK_TYPE_EVDO_0/NETWORK_TYPE_EVDO_A/NETWORK_TYPE_1xRTT
Log.d("PHONE", "getNetworkType :" + tm.getNetworkType());
단말기 종류 조회
단말기에서 지원하는 망의 종류를 반환
PHONE_TYPE_NONE/PHONE_TYPE_GSM/PHONE_TYPE_CDMA 등의 값을 반환
Log.d("PHONE", "getPhoneType :" + tm.getPhoneType());
SIM카드 Serial Number 조회
Log.d("PHONE", "getSimSerialNumber :" + tm.getSimSerialNumber());
SIM카드 상태 조회
SIM_STATE_UNKNOWN/SIM_STATE_ABSENT/SIM_STATE_PIN_REQUIRED/SIM_STATE_PUK_REQUIRED/
SIM_STATE_NETWORK_LOCKED/SIM_STATE_READY 등의 값을 반환
Log.d("PHONE", "getSimState :" + tm.getSimState());
가입자 ID 조회
GSM방식의 IMSI와 같은 가입자 ID 반환
Log.d("PHONE", "getSubscriberId :" + tm.getSubscriberId());

◆ 조회결과
getCallState :0(CALL_STATE_IDLE)
getDataState :2(DATA_ACTIVITY_OUT)
getDeviceId :000000000000000
getDeviceSoftwareVersion :null
getLine1Number :15555218135
getNetworkCountryIso :us
getNetworkOperator :310260
getNetworkOperatorName :Android
getNetworkType :3(NETWORK_TYPE_UMTS)
getPhoneType :1(PHONE_TYPE_GSM)
getSimCountryIso :us
getSimOperator :310260
getSimOperatorName :Android
getSimSerialNumber :89014103211118510720
getSimState :5(SIM_STATE_READY)
getSubscriberId :310260000000000

실제상황에서는 이와같이 현재 단말기의 상태를 직접 조회하는것이 아니라 
상태정보가 변경될 때 자동으로 인식해야하는 상황이 훨씬 많을것이다.
이럴때는 TelephonyManager의 listen()를 이용하여 콜백메서드를 등록하면 가능하다.
        tm.listen(new PhoneStateListener(){
         public void onCallStateChanged(int state, String incomingNumber){
         if (state == TelephonyManager.CALL_STATE_RINGING){
         Log.d("Telephony", "state = " + state + ", number = " + incomingNumber);
         }else{
         Log.d("Telephony", "state = " + state);
         }        
         }
        }, PhoneStateListener.LISTEN_CALL_STATE);

onCallStateChanged() 이외에도 아래와 같은 상태변화를 감지할 수 있다.
- onCallForwardingIndicatorChanged() : 호전환(Call Forwarding) 상태 변화
- onCellLocationChanged() : 단말기의 Cell위치 변화
- onDataActivity() : Data 활성화 상태 변화
- onDataConnectionStateChanged() : Data 연결상태 변화
- onMessageWaitingIndicatorChanged() : 메시지 대기상태 변화
- onServiceStateChanged() : 단말기의 서비스 상태 변화
- onSignalStrengthsChanged() : 망의 신호강도 변화

◆ 전화번호 처리
각 국가별로 전화번호의 형식이 다르다. 
한국은 01x-xxxx-xxxx 이 일반적이고,
북미는 xxx-xxx-xxxx가 된다.
PhoneNumberUtils.formatNumber() 메서드를 사용하면 설정된 Locale에 맞게 형식화 된다.
String formattedTelNumber = PhoneNumberUtils.formatNumber("01098761234");
        Log.d("Telephony", "formattedTelNumber :" + formattedTelNumber);
Locale을 English(United States)로 할경우 010-987-61234로 출력된다.
한국어로 할 경우는 01098761234가 그대로 출력된다.
formatNumber() 메서드의 구현내용을 살펴봐야 할듯 하다.

EditText에서 전화번호를 입력받을 경우에도 자동으로 형식화가 가능하다.
EditText객체의 addTextChangedListener에 PhoneNumberFormattingTextWatcher()를 등록하기만 하면 된다.
        EditText tn = (EditText) findViewById(R.id.edtTelNumber);
        tn.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
그러나 역시 한국어로는 동작하지 않았다


Android/Network | Posted by 덩치 2014. 5. 21. 14:05

AsyncTask를 이용하여 Thread 구현하기

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



Android는 Java로 되어 있어 Java에서 제공하는 기능을 사용하여 Thread를 구현할 수 있습니다. 그러나, 안드로이드 화면의 각 요소(View)에 정보를 표시한다든지 하는 UI와 관련된 작업을 하는 경우에는 여러가지 제약 사항이 따릅니다.

Google에서는 AsyncTask라는 것을 제공하여 Android에서 UI 작업과 관련된 Thread의 구현을 손쉽게 할 수 있도록 지원 합니다
 
 

  Thread with AsyncTask

UI Thread를 구현하기 위해서는 해당 Thread가 Activity에서 구현이 되어야 하며, 주고 받는 인자들의 타입이 일치 하여야 합니다. 아래 설명에서는 서로 일치해야 하는 인자들의 경우에는 동일한 색으로 표시를 해서 구분 합니다.

* AsyncTask 호출 구현
private Activity activity = null;

activity = this;
(new theAsyncThread()).execute(para1para2para3);


*AsyncTask 구현
private class theAsyncThread extends AsyncTask<StringStringString> {
    //--- Thread를 시작하기 전에 호출되는 함수
    protected void onPreExecute() {
        if ((activity != null) && (activity.isFinishing() == false)) {
            Toast.makeText(activity, "Before thread", Toast.LENGTH_SHORT).show();
        }
        super.onPreExecute();
    }

    //--- Thread의 주요 작업을 처리 하는 함수
    //--- Thread를 실행하기 위해 excute(~)에서 전달한 값을 인자로 받습니다.
    protected String doInBackground(String... arg) {
        int argCnt = 0;
        
        argCnt = arg.length;
        if (argCnt != 3) {
            return "Error";
        }
        
        //--- onProgressUpdate(~) 실행하기 위해서는 아래 함수를 호출 합니다.
        publishProgress("Thread processing.");
        return "OK";
    }

    //--- doInBackground(~)에서 호출되어 주로 UI 관련 작업을 하는 함수
    protected void onProgressUpdate(String... progress) {
        if ((activity != null) && (activity.isFinishing() == false)) {
            Toast.makeText(activity, progress[0], Toast.LENGTH_SHORT).show();
        }
    }

    //--- Thread를 처리한 후에 호출되는 함수
    //--- doInBackground(~)의 리턴값을 인자로 받습니다.
    protected void onPostExecute(String result) {
        if ((activity != null) && (activity.isFinishing() == false)) {
            Toast.makeText(activity, "After thread", Toast.LENGTH_SHORT).show();
        }
        super.onPostExecute(result);
    }

    //--- AsyncTask.cancel(true) 호출시 실행되어 thread를 취소 합니다.
    protected void onCancelled() {
        super.onCancelled();
    }      
}    





Android/View | Posted by 덩치 2014. 4. 24. 16:18

TextView에 marquee 적용하기

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


Marquee란, 전광판같은곳에서 문장을 좁은 공간에 표시하기위해


옆으로 이동하면서 숨겨진부분의 글자들이 표시되도록 하는것이다.


앞의 글자가 왼쪽으로 사라지고 뒤에 글자가 나타나는형식


Xml 레이아웃에서 텍스트뷰 속성에


        android:ellipsize="marquee"

        android:focusable="true"

        android:marqueeRepeatLimit="marquee_forever"

        android:singleLine="true"


를 추가 해 주면 된다.


첫번째는 marquee를 사용하겠다는 뜻이고,

두번째는 focusTextView가 가지고 있어야 하기때문에 설정한다.

세번째는 반복횟수인데, int값을 줘도 되고 저렇게 계~속 움직이도록 할 수 있다.

네번째는 텍스트뷰의 라인을 한줄로 표시하는것으로, 텍스트가 영역을 벗어날정도로 긴 경우에도

줄내림을 하지 않는다는것이다. 그래야 marquee가 적용된다.



아주 중요한것. 오늘 이것때문에 하루종일 씨름했는데,

setText 할 때 마다 marquee초기화되어 처음부터 표시되기에 setText가 자주 발생하는 뷰에 적용하기에는


성격이 맞지 않다.



펌 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);


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




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로 가져온 뷰를 내용에 셋팅할 수 있다.