java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/20201021_135624.jpg: open failed: EACCES(Permission denied)

테스트 도중 이런 에러가 발생했습니다. 파일 업로드 중에 발생했는데 이유를 알아보니 파일 생성 시 저장소에 관한 내용이었습니다.

앱을 삭제해도 앱 파일들은 삭제되지만 외부저장소에 있는 파일들은 앱 제거시 삭제가 되지 않는다는 것입니다.

즉 안드로이드는 앱을 제거해도 내부에 파일이 남기 때문에 구글은 이것을 보안하려고 하는 것 같습니다.

아직까지 이 부분에 대해서 많은 개발자들이 코드를 적용하지 못한 거 같아서 당장 없애진 않았네요 구글도 이 부분을 인지하고 아직 방법을 남겨 뒀습니다.

manifest에 requestLegacyExternalStorage 속성을 true로 해줍니다.

<application 
...
    android:requestLegacyExternalStorage="true" ... >
        

developer.android.com/training/data-storage/files/external-scoped

 

728x90

앱을 잘 만들고 있는 도중 에러가 발생했다.

network security policy 라고 하는 것 보니깐 네트워크 보안 정책이 바뀐 것 같다.

잘은 모르지만 기본적으론 HTTP 통신을 기본으로 허용했지만 결론적으로 HTTP 통신을 차단을 했습니다.

MANIFEST 속성이 하나 추가됐습니다. 바로 android:usesCleartextTraffic 입니다.

이 속성이 누가 버전부터 추가된 모양입니다. 저 속성은 기본 값이 FALSE 인듯 합니다.

 

그래서 가장 쉬운 해결방법은 API의 URL을 HTTP에서 HTTPS로 변경하면 됩니다.

사실 이게 쉬웠으면 좋겠지만 안드로이드 개발자 입장에서 쉽다고 할 수는 없겠죠...

다른 해결방법도 있습니다.

네트워크 보안 구성 파일 (newwork_security_config)을 만들어줍니다.

res/xml/network_security_config.xml

<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">insecure.example.com</domain>
        <domain includeSubdomains="true">insecure.cdn.example.com</domain>
    </domain-config>
</network-security-config>

그리고  manifest에 추가 해줍니다. 

<application
    ...
    android:networkSecurityConfig="@xml/network_security_config">

 

android-developers.googleblog.com/2018/04/protecting-users-with-tls-by-default-in.html

 

이런 방법도 있는데 정말 간단한 방법도 있더라고요. 그렇지만 공식 문서에서는 추천하지 않고 있습니다.

<application
    ...
   android:usesCleartextTraffic="true">

문제는 없었는데 보안상에는 안좋다고 나와있네요.

developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic

 

 

android-developers.googleblog.com/2018/04/protecting-users-with-tls-by-default-in.html

developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic

728x90

아래처럼 2개의 컬럼이 있는데 2번 idx를 삭제하고 insert를 하게되면 그 다음 번호인 3번부터 추가가 됩니다.

다시 1번부터 쓰기 위해선 초기화를 해줘야 합니다.

쿼리도 그렇게 어렵지 않습니다.

ALTER TABLE 테이블명 AUTO_INCREMENT=바꾸고 싶은 값;

이렇게 하시면 됩니다. 

728x90

안드로이드 개발 도중 android.content.res.Resources$NotFoundException:String resource ID #0x1 라는 에러가 발생했습니다.

TextView에 setText() 함수를 사용할 때 integer 타입의 데이터를 넣어서 발생하는 에러입니다.

보통은 에러가 발행하면 바로 코드에 빨간 밑줄이 발생합니다.

그렇지만 다른 함수에서 리턴을 받는 경우는 빨간 밑줄 그러니깐 에러가 발생하지 않습니다.

해결 방법은 엄청 간단합니다. 

Int 값을 String 값으로 바꿔주면 간단합니다.

728x90

개발을 하다보니 쿼리문에서 인젝션에 대한 문제들이 나오기 시작했습니다. 

그래서 쿼리문에 ? 물음표를 넣어두고 query() 함수의 두번째 파라미터 자리에 변수를 넣어줍니다.

이런식으로 사용할 수 있겠죠?

그렇다면 2개 이상은 어떻게 해야될까요?

[] 괄호를 사용하여 2번째 파라미터를 묶어주면 됩니다.

이런식으로 묶어주면 됩니다.

다른 쿼리들도 이렇게 많이 사용하는데 insert문이 조금 특이합니다.

insert into values가 보통입니다만

var sql = 'INSERT INTO table (name, email, age) VALUES(?, ?, ?)';
var params = ['hyun','94onad@naver.com','26']
connection.query(sql, params, function(err, rows, fields){

 

보통은 이렇게 많이들 쓰실텐데 INSERT문은 SET을 사용하기도 합니다. SET을 사용하게 되면 컬럼 전체를 넣어야합니다. 

  var users = {
    userid: req.body.userid,
    pwd: req.body.pwd,
    name: req.body.name,
    email: req.body.email,
    phone: req.body.phone,
    created: today,
    modified: today,
  };
  connection.query("INSERT INTO user SET ?", users, function (error, results, fields)

 

직접 쿼리문 안에 넣어주는 분들도 계시는데 이럴경우 escape() 함수를 사용하는 방법도 있습니다.

var sql = 'SELECT * FROM CLUB WHERE CLUB_SN = ' + mysql.escape(clubSn) + '; ';

 

728x90

charcter-set을 utf8로 변경 했는데 insert문을 실행하면 ?? 이렇게 물음표가 들어갔다.

이는 character set을 변경하지 전에 데이터베이스를 생성했었기 때문에 해당 데이터베이스의 character set은 변경되지 않아서 그런것입니다.

사실 이 부분에서 몇몇분은 데이터 덤프 빼놓고 다시 하시는 분들도 계시더라고요.

그리고 저는 mysql workbench에서 변경을 했는데도 계속 ?? 물음표가 들어갔습니다. 

DB와 모든 테이블에 대해서 character-set을 바꿔줘야 합니다. 조금 많이 번거롭습니다. 그래서 테이블이 많으면 그냥 다시 만드나 봅니다.

밑에 두개를 실행해 줍니다.

ALTER DATABASE [DB명] DEFAULT CHARACTER SET UTF8

ALTER TABLE [TABLE명] CONVERT TO CHARACTER SET UTF8;

해줬더니 잘 들어가네요 

728x90

비주얼 스튜디오 코드를 다운 받으면 한글패치가 되지 않은 영문판이 실행됩니다.

당황하지않고 code 에디터 안에 마켓플레이스에서 Korean Language Pack for Visual Studio Code를 설치해주면 됩니다.

영문판이니 install 누르시고 code를 껏다 키면 한글판 패치가 되어있을겁니다.

 

728x90

개발하면서 로그인을 구현하다보니 인증코드를 인증하려면 잠시 인증코드를 보관해야할 일이 생겼습니다. 그래서 잠깐 테스트 용도로 memory-cache로 코드를 짰는데 저는 Node.js 개발자가 아니다 보니깐 확인해보니 캐시에 저장하고 다른 함수에서 불러왔더니 cache가 사라져있더라고요. 정말 난감했었는데 어차피 Redis로 해야되니 Redis로 연동해보려고 합니다. Redis는 공식적으론 windows를 지원하지 않습니다만 MS Open Tech에서 개발 및 유지보수를 진행하고 있습니다. 참고로 64bit만 지원합니다.

먼저 Node.js 기본 모듈이니 express가 아니니 새로 package를 받아줘야합니다.

npm install redis

이렇게만하면 Node.js에서는 사용이 가능합니다. Redis도 DB이기 때문에 mysql이랑 연결코드가 비슷합니다.

const redis = require("redis");
const client = redis.createClient(6379, "127.0.0.1");

createClient 괄호 안은 port , host 순입니다. 나머지는 더 자세하게 알지 못하기 때문에 패스...

아무튼 이렇게 하면 redis에 접속하여 redis의 내장함수를 사용할 수 있습니다. 

예를들어 

      client.get(phone, function (err, value) {
        console.log(value);
      });

이런식으로 해당 phone이 키값이 되고 그에 대응하는 value 가 나와서 value 변수에 담깁니다.

여기까지가 node에서 redis를 사용하는 방법입니다. 

 

 

728x90

+ Recent posts