2019.01.20 20:39


안드로이드 Task의 종료시점 확인하기

배경

안드로이드는 OS에 의해 프로세스가 강제종료 되는 시점을 알 수 없다. Application 클래스의 onTerminate()메서드조차 가상머신에서만 동작하고 실제 디바이스에서는 동작하지 않는다고 문서에 명시되어 있다.(실제로도 동작하지 않는 것을 확인했다.)

Task?

안드로이드 프로세스와 태스크의 차이

안드로이드에는 Task라는 개념이 있다. Task는 어떤 앱이 실행되면서, 관련 컴포넌트(엑티비티, 서비스, 리시버, 프로바이더)를 묶어놓은 그룹의 개념으로, 프로세스와는 약간 다르다. 그렇지만, 일반적인 앱이라면 하나의 앱을 실행할 때, 하나의 프로세스가 생기며, 그 프로세스에서 실행되는 모든 컴포넌트들은 하나의 Task로 묶이게 된다. 사용자가 확인할 수 있는 최근에 실행된 앱 보기에 나오는 하나의 단위가 바로 Task 이다.


Task 종료시점 알기

OS가 프로세스를 강제종료 시키는 시점은 알 수 없지만, Task가 종료되는 시점은 알 수 있다. 즉, 사용자가 최근에 실행된 앱 보기 화면에서 태스크를 지웠을 때의 시점을 감지할 수 있는 것이다. 한개의 프로세스와 한개의 Task로 구성되어 있는 앱이라면, 이 방법을 통해 사용자가 앱을 강제종료 시키는 시점 정도는 핸들링 할 수 있다.(이것은 프로세스가 종료되는 것과는 엄밀히 다르다. 그러므로, 프로세스의 종료시점과 혼동하여 사용하면 부작용을 초래할 수 있다.)
Service 클래스에는 Task가 종료되었을 때 콜백을 받는 onTaskRemoved()메서드가 존재한다. 이 메서드를 이용해, Task의 종료시점을 잡을 수 있다.


적용방법

1.Manifest에 서비스를 등록한다. 이 때, android:stopWithTask 속성을 반드시 false로 설정해야 한다. true로 설정하면 onTaskRemoved()메서드가 호출되지 않는다.
<application
    ...>
    ...
    <service android:name=".TestService"
                android:stopWithTask="false" />
    ...
</application>
2.Manifest에 선언한 Service를 선언하고, onTaskRemoved()메서드를 오버라이드하고 필요한 내용을 구현한다.
Note : super.onTaskRemoved()를 호출하게 되면, Task가 종료되는 시점에서 프로세스는 재시작된다.(Task는 안보이고 프로세스만 살아있는 형태) Task가 종료되는 시점에서 서비스도 같이 종료시키려면 stopSelf() 메서드를 호출해준다.
public class TestService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Logger.logWarn("onTaskRemoved - " + rootIntent);
        // 여기에 필요한 코드를 추가한다.,
        
        stopSelf();
    }
}
3.해당 Service를 앱의 시작점에서 시작한다.일반적으로 앱의 시작점은 Application의 onCreate()나 스플래쉬 엑티비티의 onCreate() 메서드일 것이다. Manifest에 등록된 리시버가 없다면, 두가지 방법은 차이가 없지만, 외부 액션을 받는 리시버가 등록되어 있다면, 그 외부액션을 받았을 때 Application의 onCreate()가 실행되기 때문에, 오동작할 우려가 있으므로, 그럴때는 가급적 엑티비티의 onCreate()에서 시작하도록 한다.
public class SplashActivity extends Activity {
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startService(new Intent(this, TestService.class));
    }
    ...
}




Posted by injunech
2019.01.06 03:00


TextView 줄간격, 자간, 장평 설정하기


ㆍ 줄간격 : lineSpacingExtra, lineSpacingMultiplier

ㆍ 자간 : letterSpacing

ㆍ 장평 : textScaleX



줄 간격


android:lineSpacingExtra ="0dp"(기본)


android:lineSpacingExtra ="5dp"


android:lineSpacingMultiplier="1"(기본)


android:lineSpacingMultiplier="1.5"




자간


android:letterSpacing="0"(기본)


android:letterSpacing="0.2"


장평


android:textScaleX="1"(기본)


android:textScaleX="1.5"(기본)







Posted by injunech
2018.12.26 01:41


스크롤바(ScrollBar) 색상, 위치 변경해보기


ㆍ스크롤바의 위치와 색상 설정 방법.


<?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:background="#FFFFFF"
android:orientation="vertical"
android:gravity="center">

<ScrollView
android:layout_width="300dp"
android:layout_height="300dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="어쩌구"
android:textColor="#000000" />
</ScrollView>

</LinearLayout>


스크롤바를 항상보이게 하기

android:scrollbarFadeDuration = "0"
android:scrollbarAlwaysDrawVerticalTrack = "True"

혹은

android:scrollbarDefaultDelayBeforeFade="500000"


스크롤바 위치를 우측에서 좌측으로 바꾸기

android:VerticalScrollbarPosition = "left"


스크롤바가 밖으로, 내부 콘텐츠를 가리지 않도록 설정하기

android:scrollbarStyle="outsideInset"


스크롤바를 원하는 그림으로 변경하기, Size 변경하기


android:scrollbarThumbVertical="@drawable/scroll_thumb"
android:scrollbarSize="2dp"

스크롤바 배경 라인 변경하기


android:scrollbarTrackVertical="@drawable/scroll_track"



















Posted by injunech
2018.08.19 00:08


아래와 같은 AndroidRuntime Error 메시지 발생시

android.os.FileUriExposedException: file:///storage/emulated/0/1534602883975.jpg exposed beyond app through ClipData.Item.getUri() 

android.os.StrictMode.onFileUriExposed(StrictMode.java:1960) 

at android.net.Uri.checkFileUriExposed(Uri.java:2356) 


위와같이 FileUriExposedException 발생하는 경우 


안드로이드 7.0 부터 Uri.fromFile() 사용 시 개인 파일의 보안을 강화하기 위해 개인 디렉토리의 액세스를 제한하여 SecurityException과 FileUriExposedException이 발생할 수 있다.

따라서 Uri클래스의 fromFile()를 통해 얻어온 Uri(“file://…”)가 카메라앱으로 공유함으로써 발생한 오류이다.

따라서 해결책으로 FileProvider 사용을 해야 한다.


FileProvider 관련 Google Android 링크

android 7.0 관련 수정사항



FileProvider 사용방법

  1. res> xml> file paths.xml 파일 생성

 

  1. AndroidManifest.xml에 Provider 추가.

 

  1. Uri.fromFile() 대신 FileProvider.getUriForFile

 

 



Posted by injunech
2018.08.14 11:44


Face API in Android (1)




참고 링크 

http://www.egocube.pe.kr/translation/content/cognitive-face/201801040001



Posted by injunech
2018.05.13 19:51


[Android] Activity간 객체, 행렬 데이터 전달


ArrayList 와 행렬등의 데이터를 Activity 간 intent 에 담아서 전달하는 방법을 알아보도록 하겠습니다.


Step1. 데이터 클래스의 직렬화

우선 인자로 전달하기 위해서는 ArrayList에 담기는 데이터 클래스가 직렬화가 되어있어야 합니다.

public class User implements Serializable{

...

}


Step2. 인텐트에 데이터 담기

사용하는 방법은 동일합니다.


ArrayList<User> listUsers 객체 혹은 int [] item_list 라는 행렬등에 데이터를 담아준 상태에서

startActivity를 실행하셔서 전달하면 됩니다.

Intent it = new Intent(this, NextActivity.class);
it.putExtra("users", listUsers);
startActivity(it);

Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("item_list", item_list);
startActivity(intent);
finish();


Step3. 데이터 꺼내서 사용하기

아래와 같이 인텐트를 받는 액티비티에서 사용하시면 됩니다.


Intent intent = getIntent();
ArrayList<User> list = (ArrayList<User>) intent.getSerializableExtra("users");


Intent intent = getIntent();
item_list = (int[][]) intent.getSerializableExtra("item_list");




Posted by injunech
2018.05.08 16:56


[Android] Layout겹치기


윈도우는 빈 채로 생성되며 빈 윈도우 안에 레이아웃을 채워 넣어 UI를 구성하는데 이때는 다음 메소드를 호출 한다.

 

void setContentView(int layoutResID)

void setContentView(View view, [ViewGroup.LayoutParams params])

void addContentView(View view, ViewGroup.LayoutParams params)

 

다음 예제는 2개의 xml파일을 겹쳐서 보여주는 예제이다.

 

overlay1.xml

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

 

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="바닥 레이아웃" />

    <Button

     android:layout_width="wrap_content"

     android:layout_height="wrap_content"

     android:text="바닥의 버튼"

     />

 

</LinearLayout>

 

overlay2.xml

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

    android:gravity="center"

    android:background="#40ffff00"

>

    <TextView

     android:layout_width="wrap_content"

     android:layout_height="wrap_content"

     android:text="이것은 위쪽의 레이아웃 입니다."/>

 

    <Button

     android:layout_width="wrap_content"

     android:layout_height="wrap_content"

     android:text="위쪽 버튼"/>

 

</LinearLayout>

 

Overlay.java

 

package com.example.overlay;

 

import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.Window;

import android.widget.LinearLayout;

 

public class Overlay extends Activity {

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        Window win = getWindow();

        win.setContentView(R.layout.overlay1);

        

        //전개자로 xml파일을 가져옴

        LayoutInflater inflater = (LayoutInflater)getSystemService(

                Context.LAYOUT_INFLATER_SERVICE);

        LinearLayout linear = (LinearLayout)inflater.inflate(R.layout.overlay2null);

          

        //파라미터를 세팅해줌

        LinearLayout.LayoutParams paramlinear = new LinearLayout.LayoutParams(

                LinearLayout.LayoutParams.MATCH_PARENT,

                LinearLayout.LayoutParams.MATCH_PARENT

                );

        

        //윈도우에 추가시킴

        win.addContentView(linear, paramlinear);

        

        

    }

 

 

}

 

실행화면

 

아래쪽 레이아웃은 위쪽 레이아웃 때문에 색상이 약간 변한다. 하지만 두 버튼은 독립적으로 동작해서 클릭 리스너를 추가 시킬 수 있다.





출처: http://gakari.tistory.com/entry/안드로이드-LayoutInflater를-활용한-레이아웃-겹치기 [가카리의 공부방]



Posted by injunech
2018.04.15 01:59


Android Studio build error about gradle

Could not find com.android.tools.build.gradle:3.0.0-alpha7


위와 같이 gradle 버전을 찾지 못할때

자신의 android studio 설치 폴더상의 gradle 버전을 확인해서 build.gradle 상에 설정해준다.


 

  1. open the file path(just as the log said): file:/C:/Users/dmin/Documents/android-studio/gradle/m2repository/com/android/tools/build/gradle/
  2. found this file

  3. just change classpath 'com.android.tools.build.gradle:3.0.0-alpha7' to classpath 'com.android.tools.build.gradle:* * * ' ; * * * is the exist gradle file;

  4. buildscript {
      repositories {
        ...
        // You need to add the following repository to download the
        // new plugin.
        google()
      }
    
      dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha5'
      } 
    }







Posted by injunech
2017.12.11 17:59


[ Android Studio] 한글깨짐, File Encoding 설정


1.  Android Studio and Project File Encoding 설정


 File > Settings > Editor > File Encodings

 단축키 (Ctrl + Alt + S)

 Default 설정으로 UTF-8 로 설정 된 상태인것을 확인 한다.



2. 한글 깨진 파일 한글 정상적으로 보이게 수정 

프로젝트 파일내의 특정 코드에서 한글이 깨진경우


> Project Build 시에 아래와 같은 Encoding 에러 발생


> 아래와 같이 한글이 깨진 파일 선택


> 우측 하단에 Encoding Type 선택해서 x-windows-949 로 선택하고 팝업창 뜨면 Reload 선택



> 다시 기존 UTF-8 을 사용해야 하기 때문에 UTF-8 로 다시 선택하고 팝업창 뜨면 Convert 선택.

> 위와같이 수행하면 한글이 Android Studio Editor 에서 잘 보이고, App 에서도 깨지지 않는다.









Posted by injunech
2017.12.11 11:03


[Android] SDK 환경변수 설정


1. 환경변수 설정


> 윈도우버튼 마우스 오른쪽 버튼으로 시스템 실행 > 고급시스템 설정 > 환경 변수

> 혹은 윈도우 검색에 '시스템 환경변수 편집' 검색해서 환경변수 제어판 실행



> 환경 변수 : 시스템 변수 -> 새로만들기 


> 변수 이름에 Android-SDK, 변수 값에 본인의 Android SDK 설치 경로 입력



> 시스템변수 Path 에 JAVA JDK 폴더 경로 추가

  Android SDK 가 설치된 platform-tools 폴더 내에 adb.exe 파일이 존재한다.
  (\Android\Sdk\platform-tools)



  > Android-SDK 변수명과 platform-tools 폴더 경로를 추가하여 PATH에 환경 변수를 추가해준다.

     %Android-SDK%\platform-tools





2. Android SDK 환경변수 설정 확인


> Ctrl + R 눌러 실행 창에서 cmd 로 command 창 실행


> adb sherll 입력해서 아래와 같이 device 가 연결 된다면 완료




Posted by injunech