Failed to install the following Android SDK packages as some licences have not been accepted. 에러 해결

프로그래밍/Android (Java)|2021. 1. 25. 14:39
반응형

안드로이드 스튜디오를 새로 설치한 후 기존의 프로젝트를 불러올 경우 빌드시 아래와 같은 에러 메세지가 출력될 때가 있습니다.



[에러]

Failed to install the following Android SDK packages as some licences have not been accepted.



[해결]

안드로이드 스튜디오 메뉴 File > Settings > 출력창에서 Appearance & Behavior > System Settings > Android SDK 에서


[SDK Platforms] 탭에서 필요한 버전의 플랫폼 설치하고

[SDK Tools] 탭에서 Google Play licensing Library 를 설치해 줍니다.



그리고 빌드하면 정상 처리되는 것을 볼 수 있습니다.


반응형

댓글()

리눅스 삭제된 데이터 복원하기 (extundelete)

리눅스/OS 일반|2021. 1. 25. 12:29
반응형

[환경]

Ubuntu 18.04 LTS

OS 디스크 : SSD 250G

추가 디스크 : SATA 80G



[상황]

OS 디스크 I/O error 로 인해 교체, OS 재설치가 필요하게 되었습니다.

어차피 파쇄될 디스크지만 몇몇개의 데이터 정보 유출이 우려되어 OS 디스크의 다운로드 디렉토리와 몇가지 필요없는 파일을 수동으로 삭제하며 정리하는 도중 추가 디스크의 디렉토리를 잘못 삭제하였고, 휴지통에서 조차 비워버린 상태가 되었습니다. (모든 데이터 날아감)

(중요!!) 추가 디스크의 데이터를 안전하게 보존해야 하므로 추가 디스크에 더 이상 파일을 저장하거나 쓰면 안됩니다.



[복구]

새 OS 디스크로 교체, OS 재설치 (Ubuntu 18.10) 이후 아래 명령을 이용하였습니다.


복구에 필요한 패키지를 설치합니다.


root@cdh-desktop:~# apt -y install extundelete

root@cdh-desktop:~# apt -y install e2fslibs-dev


복구될 데이터를 저장할 디렉토리로 이동합니다.


root@cdh-desktop:~# mkdir /root/restore

root@cdh-desktop:~# cd /root/restore


삭제 파일이 있는 파티션을 지정하여 복구를 시도 합니다.

(복구 대상 디스크는 마운트가 되지 않은 상태 입니다.)


root@cdh-desktop:~/restore# extundelete /dev/sdb1 --restore-all

NOTICE: Extended attributes are not restored.

Loading filesystem metadata ... 597 groups loaded.

Loading journal descriptors ... 30268 descriptors loaded.

Searching for recoverable inodes in directory / ... 

6605 recoverable inodes found.

Looking through the directory structure for deleted files ... 

6 recoverable inodes still lost.


복구가 완료 되었습니다. 오래전에 삭제한 파일도 복구가 되어 정리를 좀 해야 하지만 다른 프로그램 과는 달리 파일명도 inode 값이 아닌 사용하던 그대로 보입니다.

감격.. ㅜ.ㅜ


(복구된 용량 확인)

root@cdh-desktop:~/restore# du -sh .

36G .


(파일 리스트 보기)

root@cdh-desktop:~/restore# ll

total 12

drwxr-xr-x 3 root root 4096  1월 25 11:58 ./

drwx------ 8 root root 4096  1월 25 11:54 ../

drwxr-xr-x 4 root root 4096  1월 25 12:10 RECOVERED_FILES/

root@cdh-desktop:~/restore# cd RECOVERED_FILES/

root@cdh-desktop:~/restore/RECOVERED_FILES# ll

total 192

drwxr-xr-x 4 root root  4096  1월 25 12:10 ./

drwxr-xr-x 3 root root  4096  1월 25 11:58 ../

drwxr-xr-x 5 root root  4096  1월 25 12:05 .Trash-1000/

drwxr-xr-x 2 root root  4096  1월 25 12:10 ISOs/

-rw-r--r-- 1 root root   527  1월 25 12:10 elcplist.dll

-rw-r--r-- 1 root root 27177  1월 25 12:10 file.4726321

-rw-r--r-- 1 root root 27570  1월 25 12:10 file.4726366

-rw-r--r-- 1 root root 24823  1월 25 12:10 file.4726383

-rw-r--r-- 1 root root 25899  1월 25 12:10 file.4726390

-rw-r--r-- 1 root root 43924  1월 25 12:10 file.4726400

-rw-r--r-- 1 root root 12716  1월 25 12:10 file.4726403

root@cdh-desktop:~/restore/RECOVERED_FILES# cd .Trash-1000/

root@cdh-desktop:~/restore/RECOVERED_FILES/.Trash-1000# ll

total 20

drwxr-xr-x 5 root root 4096  1월 25 12:05 ./

drwxr-xr-x 4 root root 4096  1월 25 12:10 ../

drwxr-xr-x 3 root root 4096  1월 25 12:05 expunged/

drwxr-xr-x 6 root root 4096  1월 25 12:05 files/

drwxr-xr-x 2 root root 4096  1월 25 12:00 info/

root@cdh-desktop:~/restore/RECOVERED_FILES/.Trash-1000# ll expunged/1651618508

total 1388

drwxr-xr-x 25 root root    4096  1월 25 12:06  ./

drwxr-xr-x  3 root root    4096  1월 25 12:05  ../

drwxr-xr-x  2 root root    4096  1월 25 12:05  G클라우드/

drwxr-xr-x 11 root root    4096  1월 25 12:05  ISMS/

-rw-r--r--  1 root root   45798  1월 25 12:05 'bookmarks_19. 1. 28.html'

drwxr-xr-x  2 root root    4096  1월 25 12:05  견적서/

drwxr-xr-x  9 root root    4096  1월 25 12:05  기술지원팀/

drwxr-xr-x  3 root root    4096  1월 25 12:05  네트워크팀/

drwxr-xr-x  3 root root    4096  1월 25 12:05  매니지드팀/

drwxr-xr-x  7 root root   12288  1월 25 12:06  보고서/

drwxr-xr-x  3 root root    4096  1월 25 12:05  보안관제/

drwxr-xr-x  2 root root    4096  1월 25 12:05  서식/

drwxr-xr-x 11 root root    4096  1월 25 12:05  인프라운영팀/



반응형

댓글()

우분투 apt-get update 404 not found 해결 방법

리눅스/OS 일반|2021. 1. 25. 11:31
반응형

Ubuntu 19.10 환경에서 겪은 내용입니다.

아래 패키지 저장소 url 을 변경 해봅니다.


# cd /etc/apt/

# cp -arp sources.list sources.list.ori

# vi sources.list


(모든 저장소의 url 을 아래 경로로 변경합니다.)


old-releases.ubuntu.com/ubuntu/


# do-release-upgrade


그다음 업데이트나 패키지를 설치해보면 잘 되는것을 볼 수 있습니다.

반응형

댓글()

안드로이드 Sound Play 사운드 재생

프로그래밍/Android (Java)|2021. 1. 21. 09:08
반응형

안드로이드 사운드 재생 방법입니다.

1. SoundPool
2. MediaPlayer

차이점이라면

SoundPool  알림사운드,게임효과등 짧은 사운드클립에 적합하고
MediaPlayer  노래와 같이 더  사운드파일을 재생할 때 적합합니다.

 

1. SoundPool 로 재생하는 방법

우선 res > raw 폴더에 sound file 을 넣습니다. (모두 소문자로! 대쉬(-)는 언더바(_)로 바꾸고)

raw 폴더가 없다면 res 에서 우클릭 -> new -> Directory 클릭 해서 raw 폴더를 만듭니다.

그럼 이제 sound play 를 위한 class를 하나 생성합니다.

MySoundPlayer.java

package ai.vdotdo.hellobryan_test;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.SoundPool;

import java.util.HashMap;

public class MySoundPlayer {
	public static final int DING_DONG = R.raw.sound_dingdong;
	public static final int SUCCESS = R.raw.success;

	private static SoundPool soundPool;
	private static HashMap<Integer, Integer> soundPoolMap;

	// sound media initialize
	public static void initSounds(Context context) {
		AudioAttributes attributes = new AudioAttributes.Builder()
				.setUsage(AudioAttributes.USAGE_GAME)
				.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
				.build();
		soundPool = new SoundPool.Builder()
				.setAudioAttributes(attributes)
				.build();

		soundPoolMap = new HashMap(2);
		soundPoolMap.put(DING_DONG, soundPool.load(context, DING_DONG, 1));
		soundPoolMap.put(SUCCESS, soundPool.load(context, SUCCESS, 2));
	}

	public static void play(int raw_id){
		if( soundPoolMap.containsKey(raw_id) ) {
			soundPool.play(soundPoolMap.get(raw_id), 1, 1, 1, 0, 1f);
		}
	}
}

SoundPool 은 Builder 를 이용해서 생성해야 합니다.

참고) new SoundPool(maxStreams, streamType, srcQuality); 로 생성하는 방식은 api21 이후에 deprecated 됐습니다.

 

사용하려는 Activity 에서는

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

		MySoundPlayer.initSounds(getApplicationContext());

		findViewById(R.id.button).setOnClickListener((v)->{
			MySoundPlayer.play(MySoundPlayer.DING_DONG);
		});
	}

MySoundPlayer.initSounds(getApplicationContext()); 로 초기화 하고

사용할 땐 
MySoundPlayer.play(MySoundPlayer.DING_DONG); 
또는

MySoundPlayer.play(MySoundPlayer.SUCCESS);

하면 됩니다.

 

2. MediaPlayer 사용.

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_dingdong); 
mediaPlayer.start();

간단하쥬?

MediaPlayer 는 사운드 외에 동영상도 재생합니다. 

 

상황에 맞게 SoundPool 과 MediaPlayer 를 사용하시면 됩니다.


[출처] https://hello-bryan.tistory.com/83

반응형

댓글()

setImageResource 에 변수를 이용해 적용하기

프로그래밍/Android (Java)|2021. 1. 20. 09:39
반응형

아래와 같이 배열을 사용하여 런타임에 이미지를 설정할 수 있습니다.


int[] images = new int[2];

images[0] = R.drawable.image1;

images[1] = R.drawable.image2;


lv.setImageResource(images[i]);



상태에 따라 배열 번호를 변경하고 싶을 경우, 배열 번호를 변경하지 않고 이미지 파일명을 변경하여 적용하면 됩니다.


int[] images = new int[1];

if (check_data.equals("first")) {

    images[0] = R.drawable.image1;

} else {

    images[0] = R.drawable.image2;

}


lv.setImageResource(images[0]);



[출처] https://stackoverflow.com/questions/5760751/android-variable-passed-for-r-drawable-variablevalue

반응형

댓글()

안드로이드에서 서버 포트 열려 있는지 확인하기 (포트 체크)

프로그래밍/Android (Java)|2021. 1. 18. 15:16
반응형
안드로이드(자바)에서 포트가 열려 있는지 확인하는 두가지 간단한 방법입니다.
timeout 을 포함 방법입니다.

    Public String result;


        // onCreate 안에 넣기

        // thread 안에 넣어주고, 결과를 출력하기 위해 하단에서 처리되기를 기다립니다.

        Thread t = new Thread(new Runnable() {

            @Override

            public void run() {

                startScan();

            }

        });

        t.start();


        // 스레드 종료 기다리기

        try {

            t.join();

        } catch (Exception e) {

            e.printStackTrace();

        }


        Toast.makeText(getBaseContext(), "결과 : " + result, Toast.LENGTH_SHORT).show();



    // onCreate 바깥에 두기

    private void startScan() {

        result = "close"; // 기본값 (포트 접근되지 않을 경우)

        try {

            Socket socket = new Socket();

            socket.connect(new InetSocketAddress("8.8.8.8", 53), 1000);

            result = "open"; // 포트 접근 될 경우 값 변경

            socket.close();

        } catch (IOException e) {

        }


    }



아래는 다른 블로그에서 가져온 방법입니다.

availablePort 함수를 위와 같이 만들고 함수를 호출해서 
리턴 값으로 결과를 확인하면 됩니다.

boolean portCheck = availablePort("192.168.2.10", 80); // 체크할 서버 IP (String) 와 포트 (Int)

 

if (portCheck) {

    System.out.println("Open"); // 결과 메세지

} else {

    System.out.println("Close"); // 결과 메세지



public boolean availablePort(String host, int port) {

    boolean result = false;

 

    try {

        (new Socket(host, port)).close();

        result = true;

    }

    catch(Exception e) {

    }


    return result;

}


[출처] https://sinwho.tistory.com/entry/JAVA-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%ED%8F%AC%ED%8A%B8-%EC%97%B4%EB%A0%A4-%EC%9E%88%EB%8A%94%EC%A7%80-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0

반응형

댓글()

시스템 모니터링 도구 zabbix 4.2.2 설치하기 (CentOS 8)

리눅스/OS 일반|2021. 1. 7. 10:18
반응형

CentOS 8 에 zabbix 설치하는 과정 입니다.

모니터링 도구 zabbix 는 기본적으로 웹서버와 DB를 필요로 합니다.

Apache, MariaDB 설치 전제 하에 작성 하였습니다.



1. 설치


# cd /usr/local/src


# yum -y install epel-release


# wget https://repo.zabbix.com/zabbix/4.2/rhel/8/x86_64/zabbix-release-4.2-2.el8.noarch.rpm

* OS 버전이 다를 경우 https://repo.zabbix.com/zabbix/4.2/rhel 에서 파일 확인이 가능합니다.


# rpm -Uvh zabbix-release-4.2-2.el8.noarch.rpm


# yum clean all


# yum -y install zabbix-server-mysql zabbix-web-mysql



2. DB 및 계정 생성


데이터 베이스를 생성 합니다.


(MySQL root 로그인 후)


MariaDB [(none)]> create database zabbix;


MariaDB [(none)]> grant all privileges on zabbix.* to zabbix@localhost identified by '12345678';


MariaDB [(none)]> flush privileges;


MariaDB [(none)]> exit


사용할 기본 테이블을 생성합니다.


# cd /usr/share/doc/zabbix-server-mysql/


# gunzip create.sql.gz


# mysql -p zabbix < create.sql


* 입력 도중 아래와 유사한 에러가 출력될 경우 해당 컬럼의 타입을 varchar 에서 text 로 변경합니다.

ERROR 1118 (42000) at line 1284: Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.


(create.sql 파일의 1352~1355 줄)

        `poc_2_phone_a`          varchar(64)     DEFAULT ''                NOT NULL,

        `poc_2_phone_b`          varchar(64)     DEFAULT ''                NOT NULL,

        `poc_2_cell`             varchar(64)     DEFAULT ''                NOT NULL,

        `poc_2_screen`           varchar(64)     DEFAULT ''                NOT NULL,


타입이 문제로 보이지 않았지만, 해당 컬럼의 타입을 varchar(64) 에서 text 로 변경 후 정상 입력되는 것을 확인 하였습니다.



3. 설정


# vi /etc/zabbix/zabbix_server.conf


// 아래 옵션은 주석을 해제하고 값을 변경해 줍니다.

DBHost=localhost

DBName=zabbix

DBUser=zabbix

DBPassword=12345678



4. 구동


# systemctl enable zabbix-server  // 시작 프로그램 등록

# systemctl start zabbix-server


zabbix 웹페이지 접근을 위해 기존 apache 데몬을 재시작 합니다.


# systemctl restart httpd


명령 실행 후 접근이 안되던 http://서버IP/zabbix 페이지에 접근이 가능합니다.



5. 접속 및 추가 설정


웹브라우저를 이용해 http://서버IP/zabbix 로 접속합니다.

아래 절차에 따라 설정을 마칩니다.


1) Welcome 메세지 확인 > [Next step] 클릭

2) 사용 가능한 PHP 모듈 및 설정 값 확인 > [Next step] 클릭

3) DB정보 입력 > [Next step] 클릭

4) Host, Port 확인 (Name 은 선택항목임) >  [Next step] 클릭

5) 지금까지의 입력값 확인 페이지  > [Next step] 클릭

6) 구성 성공 메세지 > [Finish] 클릭


모든 설정을 마치면 Username 과 Password 를 입력하는 로그인창이 뜨는데, 기본 계정은 아래와 같습니다. 보안을 위해 로그인 즉시 패스워드를 변경하도록 합니다.


- Uername : Admin  // 대소문자 구분

- Password : zabbix


* 패스워드 및 언어셋 변경

1) 우측 상단 '사람 모양' 아이콘 클릭 > [Password] 항목에서 패스워드를 변경합니다.

2) 언어도 한국어로 변경이 가능합니다. [Language] 항목에서 'ko_KR' 로 변경하면 글씨를 쉽게 읽을 수 있습니다.


반응형

댓글()

php 에서 json 파일 읽기 (2차원 배열)

프로그래밍/PHP|2021. 1. 5. 14:22
반응형

sysdocu.json


[

{ "table": "book", "id": "1", "title": "제목1", "body": "내용1" },

{ "table": "book", "id": "2", "title": "제목2", "body": "내용2" },

{ "table": "book", "id": "3", "title": "제목3", "body": "내용3" },

{ "table": "book", "id": "4", "title": "제목4", "body": "내용4" }

]



print.php


<?

$array = json_decode(file_get_contents("sysdocu.json", true));


foreach ($array as $row) {

    $table = $row->table;

    $id = $row->id;

    $title = $row->title;

    $body = $row->body;


    echo $table . "<br>";

    echo $id . "<br>";

    echo $title . "<br>";

    echo $body . "<br>";

}

?>



print.php 실행 결과


book
1
제목1
내용1
book
2
제목2
내용2
book
3
제목3
내용3
book
4
제목4
내용4



반응형

댓글()

안드로이드 제스처 이벤트 (GestureDetector) 예제

반응형

화면을 손으로 드래그시 이동 방향에 따라 이벤트가 발생하도록 하는 것이 제스처 이벤트 입니다.

아래 java 파일을 만들고 사용하고자 하는곳에서 불러오면 됩니다.



OnSwipeTouchListener.java


import android.content.Context;

import android.view.GestureDetector;

import android.view.GestureDetector.SimpleOnGestureListener;

import android.view.MotionEvent; import android.view.View;

import android.view.View.OnTouchListener;


public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener (Context ctx){

        gestureDetector = new GestureDetector(ctx, new GestureListener());

    }


    @Override

    public boolean onTouch(View v, MotionEvent event) {

        return gestureDetector.onTouchEvent(event);

    }


    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;

        private static final int SWIPE_VELOCITY_THRESHOLD = 100;


        @Override

        public boolean onDown(MotionEvent e) {

            return true;

        }


        @Override

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

            boolean result = false;

            try {

                float diffY = e2.getY() - e1.getY();

                float diffX = e2.getX() - e1.getX();

                if (Math.abs(diffX) > Math.abs(diffY)) {

                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {

                        if (diffX > 0) {

                            onSwipeRight();

                        } else {

                            onSwipeLeft();

                        }

                    }

                    result = true;

                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {

                    if (diffY > 0) {

                        onSwipeBottom();

                    } else {

                        onSwipeTop();

                    }

                }

                result = true;

            } catch (Exception exception) {

                exception.printStackTrace();

            }

            return result;

        }

    }


    public void onSwipeRight() { }


    public void onSwipeLeft() { }


    public void onSwipeTop() { }


    public void onSwipeBottom() { }


}



필요한 Activity 에서 아래 코드를 이용해 사용 합니다.


View v_swipe = (View) findViewById(R.id.v_swipe);


v_swipe.setOnTouchListener(new OnSwipeTouchListener(DetailsActivity.this) {

            public void onSwipeRight() {

                // 왼쪽에서 오른쪽으로 제스쳐 사용시 동작할 코드 넣기

            }

            public void onSwipeLeft() {

                // 오른쪽에서 왼쪽으로 제스쳐 사용시 동작할 코드 넣기

            }

            public void onSwipeTop() {

                // 아래에서 위쪽으로 제스쳐 사용시 동작할 코드 넣기

            }

            public void onSwipeBottom {

                // 위에서 아래쪽으로 제스쳐 사용시 동작할 코드 넣기

            }

        }); 



반응형

댓글()

안드로이드 소프트 키보드 숨기기

반응형

View view = this.getCurrentFocus();

if (view != null) {  

    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);

}



반응형

댓글()

HttpURLConnection 을 이용해서 http status code 받아 오기

프로그래밍/Android (Java)|2020. 12. 21. 10:16
반응형

아래와 같은 내용으로 접근하려는 웹서버의 http status code 를 확인 할 수 있습니다.

보안상의 이유로 꼭 https 로 통신하지 않으면 동작하지 않습니다.

 

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);


URL url;
HttpURLConnection connection = null;


try {
    url = new URL("https://sysdocu.tistory.com");
    connection = (HttpURLConnection) url.openConnection();
    Toast.makeText (DetailsActivity.this, "응답 결과 : " + connection.getResponseCode(), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (connection != null) {
        connection.disconnect();
    }
}

 

 

반응형

댓글()