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

,
728x90

아이맥 구입을 고려하면서 애플 서비스 센터에 전화를 걸어서 애플케어플러스에 대해 문의했다.


가입비 : 179,000원


보증기간 : 3년


2번의 우발적 손상에 대해 케어서비스 제공


액정 파손은 무상보상 조건에 해당하지 않으나, 케이플러스에 가입되면 자기부담금이 좀 저렴하게 할 수 있다.


도난, 분실에 대한 것은 해당되지 않는다.

사설 수리를 한 제품은 해당되지 않는다.


아이맥은 출장서비스를 받을 수 있다.

맥북 프로는 공식 서비스 센터에 방문해야 한다.


애플케어플러스는 처음 아이맥을 산 상태 그대로에서 이상이 생긴 걸 케어 해주는 것이기 때문에 중고로 CTO 512 SSD 로 된 것을 SSD 1TB로 교체되는지 문의해보면 안된다고 한다.

사설 수리점에서만 1TB로 교체가 가능하다.

그러므로 최신 제품을 살 때 사양을 잘 고려해서 사야 된다.

몇년 된 중고 제품을 사서 사설 수리점에서 SSD를 교체하는 걸 고려하는 것이 나을 수도 있다.


그 동안 PC에 사용되던 주력 스토리지는 최대 600MB/s의 SATA 6Gbps 대역폭 한계에 묶여 있었지만, 요즘에는 PCIe 3.0 x4 NVMe 인터페이스로 최대 속도가 3,500MB/s에 달하는 M.2 SSD들이 각광을 받고 있다.

SSD가 제공하는 속도가 보통 500MB/s 정도인데 반해서 M.2 NVMe 는 2000MB/s 또는 3000MB/s 정도 나오므로 SSD에 비해서 속도가 5~6배 차이가 난다.

보통 HDD와 2.5인치 SSD 속도가 8배 정도 차이가 난다고 하므로 M.2 NVMe 방식과 HDD는 10배 이상 속도 차이가 발생하는 셈이다.

SSD 와 M.2 NVMe 를 사용하는 유저가 부팅 속도 등은 별반 다르지 않다고 한다. 이런 부분은 부하가 심하게 걸리는 사항이 아니므로 비슷한 체감속도를 느끼는 부분일 것이다.


아이멕 사면서 Fusion 2TB 이런 걸 사는 사용자가 많은데 비싼 제품사면서 저장장치와의 인터페이스를 허접한 것으로 사용하면 제 성능을 내기 어렵다고 본다.


갈수록 동영상 편집 등을 하므로 저장장치 고용량은 대세이므로 적어도 1TB 이상을 선택하는 것이 바람직하다.

'iOS > MACBOOK' 카테고리의 다른 글

macOS 카탈리나  (0) 2020.01.16
맥북프로 SSD 교체 및 백업/복구  (0) 2020.01.08
아이맥 2015 중고 구입 검토  (0) 2020.01.04
맥북프로 2015 중고 구입 검토  (0) 2020.01.02
맥북 기본 부팅 순서 변경 방법  (0) 2019.02.14
블로그 이미지

Link2Me

,
728x90

이번에 HDD 를 교체하면서 PHP 5.6 버전 대신 PHP 7.3 버전을 설치했다.

CentOS 6.10 에 Apache 2.4 를 별도 설치했더니 PHP 와 연동이 안된다. 그래서 삭제하고 다시 설치했다.


# 삭제를 위한 리스트 확인

yum list installed | grep httpd
yum list installed | grep php


#### 삭제
yum -y remove *php*  /*패키지 중간에 php가 들어간 패키지 전체 삭제*/
yum -y remove httpd


# 제거되지 않고 남아 있는 것이 있다면 rpm -e --nodeps (의존성에 개의치 않고 삭제) 를 붙여준다.
rpm -e --nodeps 삭제모듈명



뭐가 필요하고 뭐가 불필요한지 구분하지 않고 이것저것 기본적인 걸 설치했다.


yum install -y make gcc g++ gcc-c++ autoconf automake libtool pkgconfig findutils oepnssl openssl-devel
yum install -y openldap-devel pcre-devel libxml2-devel lua-devel curl curl-devel libcurl-devel flex
yum install -y zlib zlib-devel cpp perl bison freetype freetype-devel freetype-utils
yum install -y ncurses-devel libtermcap-devel bzip2-devel
yum install -y libjpeg libjpeg-devel libjpeg-turbo-devel gd gd-devel gdbm-devel php-mbstring libexif-devel
yum install -y libmcrypt libmcrypt-devel libvpx libvpx-devel libXpm libXpm-devel icu libicu libicu-devel
yum install -y t1lib t1lib-devel gmp-devel mhash* gettext gettext-devel libtidy libtidy-devel libxslt libxslt-devel
yum install -y libedit-devel libc-client libc-client-devel pam-devel readline-devel libpng libpng-devel krb5-devel db4-devel expat*
yum install -y xml*
yum install -y gd*
yum install -y pango*
yum install -y php-devel phpize


################################
##### MariaDB 10.3 버전 설치 #####
################################
# https://tecadmin.net/install-mariadb-10-centos-redhat/ 참조하면 된다.

Step 1: Add MariaDB Yum Repositories
cat /etc/yum.repos.d/MariaDB.repo
vi /etc/yum.repos.d/mariadb.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/rhel6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

저장하고 빠져나온다.

Step 2 – Install MariaDB Server
yum -y install MariaDB-server MariaDB-client
service mysql start
service mysql stop
service mysql restart

Step 3 – Secure MariaDB Install
/usr/bin/mysql_secure_installation
root 패스워드 지정한다.

Step 4 – Working with MariaDB
mysql -u root -p
패스워드 입력

chkconfig mysql on


##############################################
##### How to Install PHP 7.4 on CentOS 6 #####
##############################################
## 설치확인
yum list installed | grep httpd
yum list installed | grep php
yum list installed | grep MariaDB


php -m | grep -i mysql
php -v
php -m

## Remi, a third-party repository which offers the latest version of PHP (7.4 / 7.3 / 7.2 / 7.1) for CentOS.
rpm -qa | grep remi-release
rpm -qa | grep epel-release
yum install -y https://rpms.remirepo.net/enterprise/remi-release-6.rpm
yum install -y --enablerepo=remi-php73 httpd php php-cli php-common php-devel php-ldap php-mbstring php-mcrypt php-mysqlnd php-pdo php-pgsql php-sqlite php-process php-snmp php-soap php-libxml php-xml php-pear php-gd
yum install -y --enablerepo=remi-php73 php-dom php-simplexml php-ssh2 php-xmlreader php-curl php-date php-exif php-filter php-ftp php-hash php-iconv php-imagick php-json php-openssl php-pcre php-posix php-sockets php-spl php-tokenizer php-zlib

# httpd.conf, php.ini 의 설정파일 찾기
find / -name httpd.conf
find / -name php.ini

## httpd.conf 파일 수정
vi /etc/httpd/conf/httpd.conf
ServerName localhost

vi /etc/php.ini
short_open_tag = On

#부팅시 자동 시작 설정
chkconfig httpd on

#서비스 구동 (apache 2.2 구동됨)
service httpd start
service httpd stop
service httpd restart


블로그 이미지

Link2Me

,

nodejs 와 MySQL 연동

node.js 2020. 2. 9. 13:42
728x90

구글에서 검색어 node-mysql 를 입력하면 https://github.com/mysqljs/mysql 를 찾을 수 있다.

Introduction 부분을 참조하면 되는데 설정 파일은 별도로 적어주는 것이 코드 보안상 필요하다.


MySQL DB 연결 설정파일을 만든다. config 디렉토리를 만든 후

vi database_mysql.js 로 필요한 정보를 적어준다.
module.exports = {
  host     : 'localhost',
  user     : 'MySQL username',
  password : 'MySQL password',
  port     : 3306,
  database : 'my_db'
};


DB 연결 테스트 파일 mysql.js 파일을 작성한다.

var dbconfig   = require('./config/database_mysql.js');
var mysql = require('mysql');
var dbconn = mysql.createConnection(dbconfig); //< DB Connection~!!

dbconn.connect(function(err){
    if(!err) {
        console.log("Database is connected!");
    } else {
        console.log("Error connecting database...nn :" + err);
    }

    var sql = "SELECT idx,userID,userNM FROM members LIMIT 2";
    dbconn.query(sql, function(error, rows, fields){
        if(error) {
            console.log(error);
        } else {
            console.log('rows',rows);
            //console.log('fields',fields);
        }
    });
    dbconn.end();
});


3. node mysql.js 를 하면 결과를 출력해줄 것이다.


rows 라고 된 부분이 select 칼럼의 결과를 출력해준다.




연결이 안되고 에러가 발생할 때 나오는 메시지

Error: connect ECONNREFUSED 127.0.0.1:3306 


DB 연결이 안되면
console.log("Error connecting database ... nn:" + err); 메시지를 전송한다.

블로그 이미지

Link2Me

,