항상 최상단에 위치하는 뷰 구현 시 문제가 발생한다.


1. '다른 앱 위에 그리기' 권한을 허용해 준다.


if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){

    Log.i("TEST", "Permission Granted ? " + Settings.canDrawOverlays(context));

    //M 이상에서만 퍼미션 확인(그 이하에서는 자동으로 허용됨)

//다른 앱 위에서 그리기 권한에 대한 허용 여부 체크

    if(Settings.canDrawOverlays(context)) {

    //이미 권한 설정 되어있음

        context.startService(new Intent(context, XXSerivce.class));

    }else{

        //권한 없음        

        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName()));

        context.startActivity(intent);    //startActivityForResult로 대체 가능

    }

}




2. 서비스에서 addView를 할 때 버전에 따라 Flag를 다르게 설정


int LAYOUT_FLAG;

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

}else{

    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;

}

WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(

  가로 크기,

세로 크기,

LAYOUT_FLAG,

WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,

PixelFormat.TRANSLUCENT);

mWindowManager.addView(표시할 뷰, mParams);




** 참고

https://stackoverflow.com/questions/46208897/android-permission-denied-for-window-type-2038-using-type-application-overlay

** 코드

private String encryption(String text) {

    try{

        MessageDigest digest = MessageDigest.getInstance("SHA-1");

        digest.update(text.getBytes("UTF-8"));

        byte[] messageDigest = digest.digest();


        StringBuffer hexString = new StringBuffer();

        for(int i=0;i<messageDigest.length;i++){

            hexString.append(String.format("%02x", 0xFF & messageDigest[i]));

        }

        return hexString.toString();

    }catch (Exception e){

        e.printStackTrace();

    }

    return "error";

}



** 추가 설명

주황색으로 된 부분에 주의.

Integer.toHexString(0xFF & messageDigest[i]) 를 사용할 시 

숫자가 한 자리일 때는 한 자리로 표시하기 때문에 (8이 '08'이 아닌 '8'이 됨)

PHP에서 sha1 암호화 한 결과값과 다를 수 있음.



ex)

PHP 에서 암호문

   7fba808629a2d0be1d0f626417b301982b441ffd

String.format(...) 사용 시 추출된 암호문 (PHP에서 암호화 한 것과 동일)

   7fba808629a2d0be1d0f626417b301982b441ffd

Integer.toHexString(...) 사용 시 추출된 암호문

   7fba808629a2d0be1df626417b31982b441ffd



** 출처

http://nanstrong.tistory.com/206

https://stackoverflow.com/questions/13747489/php-sha1-not-equal-java-sha1

RetroFit2 라이브러리 연습한 내용을 정리한 포스팅입니다.

POST방식으로, List가 포함되지 않은 단일 데이터로 이루어진 데이터를 가져오는 예제입니다.




1. Dependencies 추가


implementation 'com.squareup.retrofit2:retrofit:2.4.0'

implementation 'com.google.code.gson:gson:2.8.5'

implementation 'com.squareup.retrofit2:converter-gson:2.4.0'


Project Structure에서 추가하면 편함.




2. 데이터 모델 클래스 생성

public class Model {

    @SerializedName(키1)

    String 변수1;

    @SerializedName(키2)

    String 변수2;


    public String toString() {

        return 변수1 + " / " + 변수2;

    }

}


@SerializedName(문자열)

문자열 = JSONObject의 key 값

나중에 GsonConverterFactory에서, 해당 문자열의 키를 가진 데이터를 해당 변수에 넣음.


예를 들어 


@SerializedName("result")

String res;


가 의미하는 것은

결과로 받는 JSONObject에서 키 값이 result인 데이터를 res 안에 넣어준다는 것 같다.


키를 못 찾거나 하는 경우엔 기본 값을 넣는 것 같기도..? (String은 null, int는 0으로)





3. Interface 생성

public interface RetroFitInterface {

    @FormUrlEncoded

    @POST(URL)

    Call<Model> 메소드 (@Field(파라미터이름) 데이터타입 변수명@Field(파라미터이름2) 데이터타입 변수명 ... );

}


@FormUrlEncoded - POST 방식 사용 시 입력해야함

@POST - POST 방식을 사용한다는 의미. 괄호 안에는 연결할 페이지 URL 주소를 입력하면 된다.

나중에 BaseDomain을 입력한다면, 이곳에 입력하는 주소는 BaseDomain 이하의 주소를 입력하면 된다.

Call<Model> XX (@Field()) - 파라미터 값을 함께 보내는 경우에 사용. 뒤의 변수명은 파라미터 값 입력 시 유추할 수 있게 적당하게 넣으면 됨. 

ex) Call<Model> test (@Field("MODE") String mode)

※ String 말고 int 형이나 boolean도 자동으로 변환이 되는건지는 내일 실험해 볼 것.




4. 사용(3번과 함께 보면 좋음)

Retrofit retrofit = new Retrofit.Builder()

        .baseUrl(기본 도메인 주소)

        .addConverterFactory(GsonConverterFactory.create())

        .build();


RetroFitInterface callback = retrofit.create(RetroFitInterface.class);

Call<Model> call = callback.메소드(파라미터1, 파라미터2);


call.enqueue(new Callback<Model>() {

    @Override

    public void onResponse(Call<Model> call, Response<Model> response) {

            textView.setText("응답코드 > " + response.code() + " \n데이터 > " + response.body().toString());

    }


    @Override

    public void onFailure(Call<Model> call, Throwable t) {

        textView.setText("통신 실패");

    }

});



baseUrl(도메인주소) - 통신하려는 페이지 url이 "http://abc.com/topic/" 이라면 "http://abc.com/"이 baseUrl이다. (슬래시는 오류 방지를 위하여 추가함)

enqueue - 비동기식 통신을 할 때 사용

execute - 동기식 통신을 할 때 사용


onResponse

 - 통신 성공 시 실행된다.

 - 통신이 실패하는 경우, JSON의 파싱에 실패하는 경우에도 호출될 수 있으니, response의 code() 값과 결과값을 확인 후 처리하여야 함.

 - 데이터를 가져와서 사용할 때는 response.body() 값을 가져와서 사용.


onFailure

 - 완전한 통신 실패 시 실행


onResponse와 onFailure 둘 다 메인Thread에서 실행되므로 별도로 runOnUIThread 메소드 내부에 넣지 않아도 됨.




** 참고 사이트

http://newland435.tistory.com/25

http://yoo-hyeok.tistory.com/79

http://nobase-dev.tistory.com/6

Glide.hwp


블로그에 옮기는 건 이다음으로..

https://medium.com/@amsanjeev/adding-translate-api-to-android-apps-788c5bca5521

+ Recent posts