[Android] SharedPreference 를 이용한 앱 접속 유지

2024. 3. 29. 12:10기술 창고/App

728x90
SMALL

앱을 만들어 배포하게 될 때, 해당 앱을 껏다가 켜도 기존의 접속된 상태를 유지시키면서 자동적으로 진행 중이였던 작업 상황이나 데이터를 불러오기 위한 방법 중 SharedPreference 가 있습니다.

 

SharedPreference 는 말 그대로 앱을 사용하고자 하는 기기의 공유 환경설정을 관리할 수 있습니다.

웹 환경에서는 쿠키나 세션으로 관리해줄 수 있지만 앱에서는 이 SharedPreference로 관리해줄 수 있는 것입니다.

다만 세션이랑 쿠키랑 마찬가지로 엄청 많거나 큰 크기의 데이터를 저장하고 관리해줄 수는 없습니다.

물론, 단순히 접속 유지만을 위해 사용할 것이기 때문에 SharedPreference 를 사용해서 굳이 과도한 데이터를 저장할 가능성은 없다고 봅니다.

 

 

SharedPreferences로 데이터 저장하기

저장하려는 키-값 컬렉션이 비교적 작은 경우 SharedPreferences  API를 사용할 수 있습니다. 

SharedPreferences 객체는 키-값 쌍이 포함된 파일을 가리키며 키-값 쌍을 읽고 쓸 수 있는 간단한 메서드를 제공합니다.

 SharedPreferences 파일은 프레임워크에서 관리하며 비공개이거나 공유일 수 있습니다.

 

 

공유 환경설정의 핸들 가져오기

SharedPreferences  에서 제공해주는 함수들을 통해 공유 환경설정 파일을 생성하거나 기존 파일에 액세스할 수 있습니다.

 

- getSharedPreferences()

이름으로 식별되는 공유 환경설정 파일이 여러 개 필요한 경우 이 메서드를 사용합니다.

이름은 첫 번째 매개변수로 지정할 수 있습니다.

앱의 모든 Context에서 이 메서드를 호출할 수 있습니다.

 

- getPreferences()

안드로이드 스튜디오 프로젝트에서의 Activity에 공유 환경설정 파일을 하나만 사용해야 하는 경우 Activity에서 이 메서드를 사용합니다.

이 메서드는 활동에 속한 기본 공유 환경설정 파일을 검색하기 때문에 이름을 제공할 필요가 없습니다.

 

즉, getSharedPreferences() 는 다수의 공유 환경설정 파일을, getPreferences는 단일의 공유 환경설정 파일을 관리해줍니다.

 

 

코드 작성 - [ 공유 환경설정 생성 및 작성 후 반영 ]

백엔드 서버 호출 api

public DeviceResponseDto getSupplierCode(HttpServletResponse response, String dc){
    log.info("service 단으로 넘어온 기기 코드 : {}", dc);

    // 공급사 코드 추출
    String supplierCode = deviceQueryData.getSupplierCode(dc);

    // Json으로 파싱한 반환 데이터
    JSONObject responseJson = new JSONObject();
    responseJson.put("supplierCode", supplierCode);

    // 헤더 생성 및 데이터 저장
    response.addHeader("supplier", supplierCode);
    response.addHeader("device", dc);
    
    // 반환 객체
    DeviceResponseDto responseDto = DeviceResponseDto.builder()
            .supplierCode(supplierCode)
            .build();

    return responseDto;
}

안드로이드 앱과 소통할 백엔드 서버의 api 서비스 코드입니다.

정상적으로 http 요청이 수행되면, supplierCode 라는 응답 반환 데이터가 저장되어 반환되고, Response에 supplier, device 라는 헤더가 생성되고 데이터가 저장되어 반환될 것입니다.

 

 

안드로이드 스튜디오 코드

btnGetDeviceID.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    
        // HttpUrlConnection
        Thread th = new Thread(new Runnable() {
        
            @Override
            public void run() {
                try {
                    
                    // Http 요청
                    Request request = new Request.Builder()
                            .url("http://localhost:8090/test?dc=" + "dc001")
                            .get()
                            .build();

                    // 비동기 방식으로 요청 전송
                    client.newCall(request).enqueue(new okhttp3.Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            e.printStackTrace();
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if (!response.isSuccessful()) {
                                throw new IOException("Unexpected code " + response);
                            }

                            // 공유 환경설정 파일 생성 + 편집 기능 호출
                            SharedPreferences rfidSharedPreference = getContext().getSharedPreferences("RfidAccessPreference", Context.MODE_PRIVATE);
                            SharedPreferences.Editor edit = rfidSharedPreference.edit();

                            try {
                                // 응답받은 데이터를 String 타입으로 반환 저장
                                String responseData = response.body().string();
                                // 반환 데이터를 Json 형식의 데이터로 파싱
                                JSONObject jsonResponseData = new JSONObject(responseData);

                                // 반환받은 Json 데이터 중 supplierCode라는 이름의 데이터를 추출 후 String으로 저장
                                String supplierCode = jsonResponseData.getString("supplierCode");
                                
                                // 공유 환경설정 작성
                                edit.putString("1", supplierCode + "-" + response.header("device") + "-" + response.header("supplier"));
                                edit.putString("device_code", "dc001");
                                
                                // 공유 환경설정 저장 및 반영
                                edit.apply();
                                edit.commit();

                                TagScanFragmentNew.expressSupplierCode.setText(supplierCode);

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });

                } catch (Exception e) {
                    Log.i("tag", "error :" + e);
                }
            }
        });
        
        th.start();
    }
});

버튼을 만들어주고, 누르면 http 요청을 통해 백엔드 서버와 통신한 뒤, 정상적으로 반환값이 전달되면 SharedPreference의 공유 환경설정 파일을 생성 및 저장하고, 접속 유지 파악을 위한  TagScanFragmentNew 클래스의 expressSupplierCode에 응답값을 넣어주는 코드를 만들었습니다.

 

여기서 봐야할 부분은, 

 // 공유 환경설정 파일 생성 + 편집 기능 호출
SharedPreferences rfidSharedPreference = getContext().getSharedPreferences("RfidAccessPreference", Context.MODE_PRIVATE);
SharedPreferences.Editor edit = rfidSharedPreference.edit();

// 공유 환경설정 작성
edit.putString("1", supplierCode + "-" + response.header("device") + "-" + response.header("supplier"));
edit.putString("device_code", "dc001");
                                
// 공유 환경설정 저장 및 반영
edit.apply();
edit.commit();

이 세 부분입니다.

 

(1)

Context 혹은 Activity에 getSharedPreferences 함수를 통해 RfidAccessPreference라는 이름의 환경설정 파일을 접속 권한을 private으로 지정하여 만들고 호출합니다.

불러온 환경설정 파일에 내용을 넣어줄 수 있는 Editor를 호출합니다.

 

(2)

호출한 Editor에 put 함수를 통해 데이터를 넣어줍니다.

위의 코드에서는 putString 함수를 사용함으로서 String 타입의 데이터를 넣어주었습니다.

1이라는 키 값에 저는 응답값으로 받은 supplierCode와 Response Header 인 device와 supplier의 값을 합쳐서 넣어주었습니다.

또 추가로 device_code라는 키로 dc001이라는 값을 넣어주었습니다.

 

(3)

apply()와 commit()을 통해 작성된 환경설정 파일을 반영해주었습니다.

 

 

코드 작성 - [ 공유 환경설정 확인 후 접속 유지 ]

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    // 공유 환경설정 호출
    SharedPreferences sharedPref = getActivity().getSharedPreferences("RfidAccessPreference", Context.MODE_PRIVATE);
    // 호출 시 조회할 공유 환경설정 파일의 기본값
    String defaultValue = "NON_EXIST_PREFERENCE";
    // 공유 환경설정 파일의 1이라는 키값을 호출
    String accessPreference = sharedPref.getString("1", defaultValue);
    // 공유 환경설정 파일의 device_code라는 키값을 호출
    String deviceCodePreference = sharedPref.getString("device_code", defaultValue);

    // 만약 호출한 공유 환경설정 파일의 키값이 정상적으로 불러와지고 호출되었을 경우 진입
    if (!accessPreference.equals(defaultValue) && accessPreference != null &&
            !deviceCodePreference.equals(defaultValue) && deviceCodePreference != null) {
        // accessPreference의 호출 데이터를 - 기호 기준으로 리스트화
        String[] accessInfo = accessPreference.split("-");
        
        // 스레드 http 요청
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
					// https 요청 정보
                    Request request = new Request.Builder()
                            .url("http://localhost:8090/supplier?dc=" + accessInfo[0])
                            .get()
                            .build();


                    // 비동기 방식으로 요청 전송
                    client.newCall(request).enqueue(new okhttp3.Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            e.printStackTrace();
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if (!response.isSuccessful()) {
                                throw new IOException("Unexpected code " + response);
                            }

                            try {
                                // 응답 데이터를 가지고 json 형식으로 파싱
                                String responseData = response.body().string();
                                JSONObject jsonResponseData = new JSONObject(responseData);
                                
                                // json 데이터 중 supplierCode 데이터 추출 후 TagScanFragmentNew.expressSupplierCode에 저장
                                String supplierCode = jsonResponseData.getString("supplierCode");
                                TagScanFragmentNew.expressSupplierCode.setText(supplierCode);

                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                        }
                    });

                } catch (Exception e) {
                    Log.i("tag", "error :" + e);
                }
            }
        });
        
        th.start();
    }
}

위의 코드는 앱 실행 시 메인 화면이 구성되는 파일의 View가 생성되어지는 onViewCreated 함수의 코드 내부입니다.

정상적으로 환경설정 파일의 유지 데이터 정보들이 조회되고 호출 되면 반응하는 코드 동작 코드들입니다.

 

여기서 중점적으로 볼 부분은,

// 공유 환경설정 호출
SharedPreferences sharedPref = getActivity().getSharedPreferences("RfidAccessPreference", Context.MODE_PRIVATE);
// 호출 시 조회할 공유 환경설정 파일의 기본값
String defaultValue = "NON_EXIST_PREFERENCE";
// 공유 환경설정 파일의 1이라는 키값을 호출
String accessPreference = sharedPref.getString("1", defaultValue);
// 공유 환경설정 파일의 device_code라는 키값을 호출
String deviceCodePreference = sharedPref.getString("device_code", defaultValue);

// 만약 호출한 공유 환경설정 파일의 키값이 정상적으로 불러와지고 호출되었을 경우 진입
if (!accessPreference.equals(defaultValue) && accessPreference != null &&
     !deviceCodePreference.equals(defaultValue) && deviceCodePreference != null) {
     
     ... (동작 처리 코드)
     
}

이 부분들입니다.

 

(1)

Activity에 getSharedPreferences 함수를 통해 위에서 만들어준 RfidAccessPreference 라는 이름의 환경설정 파일을 호출합니다.

 

(2)

호출한 환경설정 파일에서 정보들을 추출할 때, 만약 원치않는 데이터가 존재하거나 데이터가 존재하지 않거나 할 때에 보여지게될 기본 디폴트 값이 필요합니다.

따라서 defaultValue라는 이름의 변수에 기본 값을 설정해줍니다.

 

(3)

getString 함수를 통해 "1", "device_code" 라는 환경설정 정보들을 호출하면서, defaultValue도 넣어주어 호출합니다.

 

(4)

만약 호출한 정보들이 존재하고, defaultValue값이 아니라면 정상적으로 if문의 동작 처리 코드가 수행됩니다.

 

 

 

결과

 

이처럼 처음에는 설정 공급사 코드라는 부분에 아무런 정보가 나오지 않고, 코드를 입력한 뒤 공급사 코드가 적용된 상태에서 앱을 완전히 껏다가 다시 실행 시 접속 정보가 유지된 채 공급사 코드가 지속해서 유지되어있는 것을 볼 수 있습니다.

 

728x90
반응형
LIST