728x90

안드로이드폰에서 폴더에 있는 text 파일을 읽어서 미리보기하는 기능이 필요하여 구현해봤다.


테스트 환경 : LG G5 테스트 성공, Samsung S10 실패


XML 파일

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_fileread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"
        android:text="File Read"
        android:textAllCaps="false"/>
</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linear_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffffff">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/popupTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:gravity="center"
            android:text="읽은 파일 미리보기"
            android:textSize="18sp"
            android:textStyle="bold"
            android:background="@color/colorPrimary"/>

        <TextView
            android:id="@+id/popupSaveBtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="적용"
            android:textSize="18sp"
            android:textStyle="bold"
            android:background="#B5FFD5"/>

        <TextView
            android:id="@+id/popupCancelBtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="취소"
            android:textSize="18sp"
            android:textStyle="bold"
            android:background="#FFFF00"/>

    </LinearLayout>

    <ScrollView
        android:id="@+id/popupScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000000">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/popupText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:ellipsize="start"
                android:gravity="left"
                android:textColor="#FFFFFF"
                android:textStyle="bold" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>


갤럭시 S10에서 안되는 이유는 사용된 코드가 오래된 코드라서 그렇더라.

인터넷에서 찾아서 테스트한 코드가 매우 오래된 코드라서 보안이 강화된 폰에서는 읽어내질 못하더라.

주황색으로 표시된 코드를 다른 코드로 찾아서 대체하면 해결될 것이다.

최신폰에서 동작되도록 하는 것은 개발자 각자의 몫으로....

미리 보기를 위한 팝업창 코드에는 전혀 문제가 없다는 것도 확인했다.

에러 때문에 좀 삽질을 하기는 했지만.


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    Context mContext;

    Button popup_alert;
    String select_filePath;
    ScrollView pScrollView;
    View popupView;

    private static final int READ_REQUEST_CODE = 42;

    protected View mPopupView; // 팝업 뷰

    private void initView() {
       // 1. 특정 폴더에 있는 파일 읽어서 미리보기 화면에 보여주기
        popup_alert = findViewById(R.id.btn_fileread);
        popup_alert.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_fileread:
                popupView = view;
                showFileChooser();
                break;
        }
    }

    private void showFileChooser() {
        Intent intent;
        if (android.os.Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
            intent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
            intent.putExtra("CONTENT_TYPE", "*/*");
            intent.addCategory(Intent.CATEGORY_DEFAULT);
        } else {

            String[] mimeTypes =
                    {"application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", // .doc & .docx
                            "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", // .ppt & .pptx
                            "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xls & .xlsx
                            "text/plain",
                            "application/pdf",
                            "application/zip", "application/vnd.android.package-archive"};

            intent = new Intent(Intent.ACTION_GET_CONTENT); // or ACTION_OPEN_DOCUMENT
            intent.setType("*/*");
            intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
        }

        try {
            startActivityForResult(Intent.createChooser(intent, "Select a File"), READ_REQUEST_CODE);
        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(this, "Please install a File Manager.",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case READ_REQUEST_CODE:
                if (resultCode == RESULT_OK) {
                    // Get the Uri of the selected file
                    Uri uri = data.getData();
                    select_filePath = getRealPathFromURI(uri); // 이 함수를 다른 걸로 대체하는게 공부
                    Log.e(TAG, "file_path = " + select_filePath);
                    if(select_filePath != null){
                        mPopupWindowShow(readFile(select_filePath));
                    }
                }
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    private String getRealPathFromURI(Uri uri) {
        String filePath = "";
        filePath = uri.getPath();
        //경로에 /storage가 들어가면 real file path로 판단
        if (filePath.startsWith("/storage"))
            return filePath;

        String wholeID = DocumentsContract.getDocumentId(uri);

        //wholeID는 파일명이 abc.zip이라면 /document/B5D7-1CE9:abc.zip와 같다.
        // Split at colon, use second item in the array
        String id = wholeID.split(":")[1];

        Log.e(TAG, "id = " + id);

        String[] column = { MediaStore.Files.FileColumns.DATA };

        //파일의 이름을 통해 where 조건식을 만든다.
        String sel = MediaStore.Files.FileColumns.DATA + " LIKE '%" + id + "%'";

        //External storage에 있는 파일의 DB를 접근하는 방법이다.
        Cursor cursor = getContentResolver().query(MediaStore.Files.getContentUri("external"),
                column, sel, null, null);

        int columnIndex = cursor.getColumnIndex(column[0]);

        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
        return filePath;
    }

    private String readFile(String filepath) {
        File fileEvents = new File(filepath);
        StringBuilder text = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new FileReader(fileEvents));
            String line;
            while ((line = br.readLine()) != null) {
                text.append(line);
                text.append('\n');
            }
            br.close();
        } catch (IOException e) { }
        String result = text.toString();
        return result;
    }

    public void mPopupWindowShow(String url) {
        Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        Point point = new Point();
        display.getSize(point);
        int height = (int) (point.y * 0.8);
        int width = (int) (point.x * 0.9); // Display 사이즈의 90%

        // inflate the layout of the popup window
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.popup_window,null);
        mPopupView = layout.findViewById(R.id.linear_layout);

        TextView popupTitle = layout.findViewById(R.id.popupTitle);
        popupTitle.setText("내용 미리보기");
        TextView popupSave = layout.findViewById(R.id.popupSaveBtn);

        TextView popupCancel = layout.findViewById(R.id.popupCancelBtn);

        pScrollView = layout.findViewById(R.id.popupScrollView);
        TextView popupContent = layout.findViewById(R.id.popupText);
        popupContent.setText(url);

        pScrollView.setVerticalScrollBarEnabled(true); // 수직방향 스크롤바 사용 가능하도록 설정
        popupContent.setMovementMethod(new ScrollingMovementMethod());
        popupContent.setTextSize(12);

        // create the popup window
        boolean focusable = true; // lets taps outside the popup also dismiss it
        final PopupWindow popupWindow = new PopupWindow(mPopupView, width, height, focusable);

        popupWindow.showAtLocation(popupView, Gravity.BOTTOM, 0, 0); // Parent View 로부터의 위치

        popupSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(mContext, "적용을 시작합니다.", Toast.LENGTH_SHORT).show();
            }
        });

        popupCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (popupWindow != null && popupWindow.isShowing()){
                    popupWindow.dismiss();
                }
            }
        });
    }

}




블로그 이미지

Link2Me

,