Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

안드로이드에서 런타임 권한으로 외부 저장소에 TXT 파일 생성하는 방법

이 글에서는 안드로이드(Android)에서 런타임 권한(Runtime Permission)을 활용해 외부 저장소(External Storage)에 txt 파일을 생성하는 방법을 단계별로 살펴봅니다.

1단계 — 새 프로젝트 생성

Android Studio에서 File → New Project를 선택하고, 필요한 정보를 모두 입력하여 새 프로젝트를 생성합니다.

2단계 — 레이아웃 작성

res/layout/activity_main.xml에 아래 코드를 추가합니다.

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "https://schemas.android.com/apk/res/android"
    xmlns:tools = "https://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = ".MainActivity"
    android:orientation = "vertical">
    <EditText
        android:id = "@+id/enterText"
        android:hint = "Please enter text here"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content" />
    <Button
        android:id = "@+id/save"
        android:text = "Save"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content" />
</LinearLayout>

위 코드에는 EditText와 Button이 배치되어 있습니다. 사용자가 버튼을 클릭하면 EditText에 입력된 내용을 가져와 외부 저장소에 저장하는 구조입니다.

3단계 — MainActivity.java 작성

src/MainActivity.java에 다음 코드를 추가합니다.

package com.example.andy.myapplication;

import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 100;
    Button save;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final EditText enterText = findViewById(R.id.enterText);
        save = findViewById(R.id.save);
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!enterText.getText().toString().isEmpty()) {
                    String state = Environment.getExternalStorageState();
                    if (Environment.MEDIA_MOUNTED.equals(state)) {
                        if (Build.VERSION.SDK_INT >= 23) {
                            if (checkPermission()) {
                                File sdcard = Environment.getExternalStorageDirectory();
                                File dir = new File(sdcard.getAbsolutePath() + "/text/");
                                dir.mkdir();
                                File file = new File(dir, "sample.txt");
                                FileOutputStream os = null;
                                try {
                                    os = new FileOutputStream(file);
                                    os.write(enterText.getText().toString().getBytes());
                                    os.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            } else {
                                requestPermission(); // 권한 요청 코드
                            }
                        } else {
                            File sdcard = Environment.getExternalStorageDirectory();
                            File dir = new File(sdcard.getAbsolutePath() + "/text/");
                            dir.mkdir();
                            File file = new File(dir, "sample.txt");
                            FileOutputStream os = null;
                            try {
                                os = new FileOutputStream(file);
                                os.write(enterText.getText().toString().getBytes());
                                os.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        });
    }
    private boolean checkPermission() {
        int result = ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (result == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            return false;
        }
    }

    private void requestPermission() {
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            Toast.makeText(MainActivity.this, "Write External Storage permission allows us to create files. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.e("value", "Permission Granted, Now you can use local drive .");
            } else {
                Log.e("value", "Permission Denied, You cannot use local drive .");
            }
            break;
        }
    }
}

핵심 로직을 간단히 설명하면 다음과 같습니다.

  • checkPermission(): WRITE_EXTERNAL_STORAGE 권한이 이미 부여되었는지 확인합니다.
  • requestPermission(): 권한이 없으면 시스템 권한 요청 다이얼로그를 호출합니다. 이전에 거부한 적이 있다면 앱 설정에서 직접 허용하도록 안내 메시지를 표시합니다.
  • onRequestPermissionsResult(): 권한 요청 결과를 받아 승인 여부를 로그로 출력합니다.

4단계 — 매니페스트 설정

manifest.xml에 다음 코드를 추가합니다. 외부 저장소 읽기·쓰기 권한이 반드시 선언되어 있어야 합니다.

<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "https://schemas.android.com/apk/res/android"
    package = "com.example.andy.myapplication">
    <uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE"/>
    <application
        android:allowBackup = "true"
        android:icon = "@mipmap/ic_launcher"
        android:label = "@string/app_name"
        android:roundIcon = "@mipmap/ic_launcher_round"
        android:supportsRtl = "true"
        android:theme = "@style/AppTheme">
        <activity android:name = ".MainActivity">
            <intent-filter>
                <action android:name = "android.intent.action.MAIN" />
                <category android:name = "android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

앱 실행 및 결과 확인

이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤 툴바의 Run 아이콘을 클릭하고, 목록에서 자신의 모바일 기기를 선택하면 기기에 앱의 기본 화면이 표시됩니다.

안드로이드에서 런타임 권한으로 외부 저장소에 TXT 파일 생성하는 방법

위 화면에서 텍스트를 입력한 후 Save 버튼을 클릭합니다.

안드로이드에서 런타임 권한으로 외부 저장소에 TXT 파일 생성하는 방법

앱을 처음 실행하면 외부 저장소 접근을 위한 런타임 권한 요청 다이얼로그가 나타납니다. 권한을 허용하면 파일이 정상적으로 저장됩니다. 결과를 검증하려면 기기의 외부 저장소를 열어 'text' 폴더와 그 안의 sample.txt 파일이 생성되었는지 확인하면 됩니다.

안드로이드에서 런타임 권한으로 외부 저장소에 TXT 파일 생성하는 방법

참고: 최신 안드로이드 버전에서의 주의사항

Android 10(API 29)부터는 범위 지정 저장소(Scoped Storage) 정책이 도입되어 WRITE_EXTERNAL_STORAGE 권한만으로는 공용 저장소에 자유롭게 쓰기가 어렵습니다. Android 11 이상을 대상으로 한다면 MediaStore API나 앱 전용 디렉터리(getExternalFilesDir()) 사용을 고려하는 것이 좋습니다. 위 예제는 Android 9(API 28) 이하 환경에서 가장 잘 동작합니다.