전체 글

1 2 3 4 5 6 ··· 8

지문인식 구현하기

1. AndroidManifest.xml 권한추가

2. gradle dependency추가

3. java코드 추가


1. AndroidManifest.xml 권한추가

<!-- 지문인식 권한부여 -->
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>

 

2. gradle dependency추가

implementation 'androidx.biometric:biometric:1.0.1'

 

3. java코드 추가

public class MainActivity extends AppCompatActivity {

    private Executor executor;
    private BiometricPrompt biometricPrompt;
    private BiometricPrompt.PromptInfo promptInfo;

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


        executor = ContextCompat.getMainExecutor(this);
        biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
            @Override
            public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
                super.onAuthenticationError(errorCode, errString);
                Toast.makeText(getApplicationContext(), "인증에러!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAuthenticationSucceeded(
                    @NonNull BiometricPrompt.AuthenticationResult result) {
                super.onAuthenticationSucceeded(result);
                Toast.makeText(getApplicationContext(), "인증성공!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAuthenticationFailed() {
                super.onAuthenticationFailed();
                Toast.makeText(getApplicationContext(), "인증실패!", Toast.LENGTH_SHORT).show();
            }
        });

        promptInfo = new BiometricPrompt.PromptInfo.Builder()
                .setTitle("지문 인증")
                .setNegativeButtonText("취소")
                .setDeviceCredentialAllowed(false)
                .build();
    }
}

지문인식을하기 위한 기본 설정은 완료했습니다.

 

마지막으로 실행시키기 위해서 아래코드를 원하는 동작에 입력해주시면 됩니다.

biometricPrompt.authenticate(promptInfo);

취소하기 위해서는 cancelAuthentication()을 사용하시면 됩니다.

biometricPrompt.cancelAuthentication();

 



SQLite 백업 및 복구


백업 및 복구를 하기 전에 storage에 접근하기 위한 permission 권한을 가지고 있어야 합니다.

AndroidManifest.xml에서 manifest태그 안에 읽기와 쓰기에 대한 권한을 부여해줍니다.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

 

 

 

*백업*

앱 내부에 있는 파일을 스마트폰 저장공간(/Download)으로 복사하는 코드입니다.

getExternalStorageDirectory()는 /storage/emulated/0

getDataDirectory()는 /data

위치값을 가져옵니다.

FileChannel을 이용해서 파일을 복사해주고 close로 닫아주면 됩니다.

try {
	File sd = Environment.getExternalStorageDirectory();
	File data = Environment.getDataDirectory();

	if (sd.canWrite()) {
		File currentDB = new File(data, "/data/패키지명/databases/파일명");
		File backupDB = new File(sd, "/Download/파일명");

		FileChannel src = new FileInputStream(currentDB).getChannel();
		FileChannel dst = new FileOutputStream(backupDB).getChannel();
		dst.transferFrom(src, 0, src.size());

		src.close();
		dst.close();
		Snackbar.make(getView(), "백업이 완료되었습니다.", Snackbar.LENGTH_SHORT).show();
	}
} catch (Exception e) {
	Snackbar.make(getView(), "백업이 실패되었습니다.", Snackbar.LENGTH_SHORT).show();
}

 

*복원*

백업과 반대로 스마트폰 저장공간에 있는 파일을 앱 내부 공간으로 복사합니다.

try {
	File sd = Environment.getExternalStorageDirectory();
	File data = Environment.getDataDirectory();

	if (sd.canWrite()) {
		File currentDB = new File(sd, "/Download/DB파일");
		File restoreDB = new File(data, "/data/패키지명/databases/DB파일");

		FileChannel src = new FileInputStream(currentDB).getChannel();
		FileChannel dst = new FileOutputStream(restoreDB).getChannel();
		dst.transferFrom(src, 0, src.size());

		src.close();
		dst.close();
		Snackbar.make(getView(), "복구가 완료되었습니다.", Snackbar.LENGTH_SHORT).show();
	}
} catch (Exception e) {
	Snackbar.make(getView(), "복구에 실패하였습니다.", Snackbar.LENGTH_SHORT).show();
}

 

※ 추가정보

- 파일 복사가 아닌 파일 이동의 경우 currentDB.delete()로 제거하면 됩니다.

 

try문에 진입하지 않고 catch로 넘어갈 경우

- catch에 어떤부분이 문제가 생겼는지 Log로 확인하면 됩니다.

-실행했을 때 제대로 실행되지 않고 open failed: EACCES (Permission denied)라고 예외처리가 되면 접근권한이 없으므로

  manifest에 퍼미션 추가해주셔야합니다.

  manifest - application 태그 안에 android:requestLegacyExternalStorage="true"를 작성하면 정상적으로 접근가능합니다.

 

try문은 진입했으나 if문을 들어가지 않을 경우

- sd.canWrite가 false를 반환하고 있을겁니다.

  이 경우에는 앱에서 저장공간 액세스 권한이 없으므로 "설정-애플리케이션-앱-권한"에 들어가서 액세스 허용을 시켜줘야 합니다. 

  (퍼미션체크 설정: sseong66.tistory.com/64 )



Date to String

&

String to Date

변환하기


Date to String

 

- Calendar 객체를 생성하여 현재 날짜와 시간정보를 가져옵니다.

Calendar calendar = Calendar.getInstance();

- 원하는 Date 형식을 지정.

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

- 가져온 정보를 format 후 String으로 저장.

String date = dateFormat.format(calendar.getTime());

String to Date

 

- String 타입으로 되어있는 날짜값이 어떤값인지 알기 위해서 SimpleDateFormat으로 맞춰줍니다.

  그리고 parse를 이용해서 Date 변수에 담아주면 됩니다.

  ( ※ parse는 try-catch문 안에서 사용하지 않을 경우 에러가 발생합니다. )

Date parse_date = null;
String date = "20200101";
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyyMMdd");

try {

	parse_date = dateFormat1.parse(date);
    
}catch (Exception e){ e.printStackTrace(); }

 



Preferences 앱 설정화면

with PreferenceFragmentCompat


PreferenceActivity를 사용하려고 했는데 API 29부터는 deprecated 되기 때문에 대안으로

PreferenceFragmentCompat을 이용해서 사용할 수 있습니다.

PreferenceFragmentCompat은 Activity가 아니라서 AndroidManifest에 등록이 되지 않습니다.

해결방법은 AppCompatActivity를 상속한 레이아웃을 만들어서 android:name으로 클래스를 선언해주시면 됩니다.

 

 


 gradle 추가

∨ Toolbar 생성 및 설정

 menu 생성

∨ onCreateOptionsMenu, onOptionItemSelected 메서드 오버라이드

res/xml/user_preference.xml 파일생성 & PreferenceFragmentCompat 상속받은 UserPreferences 클래스 생성

∨ res/layout/preferences.xml 파일생성 & AppCompatActivity 상속받은 PreferencesActivity 클래스 생성

∨ manifest.xml에 해당 Activity 추가


 

implementation 'androidx.preference:preference:1.1.0'

gradle에 preference 추가.

 

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
// 툴바 설정
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

xml에 Toolbar 추가하고 java파일에 설정.

 

res 우클릭 - New - Android Resource Directory에서 menu 폴더를 생성해줍니다.

생성한 menu폴더 우클릭 - New - Menu Resource File로 원하는 이름으로 메뉴 xml 파일을 생성해주세요.

 

menu_main.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_settings"
        android:title="settings"
        android:icon="@drawable/ic_baseline_settings_24"
        app:showAsAction="always"/>
</menu>

생성한 menu파일에 추가하려는 버튼을 item으로 추가시킵니다.

app:showAsAction은 액션바에 바로 보이게하거나 버튼을 눌렀을 때 보이게하도록 설정할 수 있습니다.

 

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        switch (item.getItemId()){
            case R.id.action_settings:
                startActivity(new Intent(this, PreferencesActivity.class));
                break;
        }
        return super.onOptionsItemSelected(item);
    }

onCreateOptionMenu와 onOPtionsItemSelected를 오버라이드 해줍니다.

onCreateOptionMenu로 액션바에 메뉴를 추가하고,

onOptionsItemSelected로 해당 버튼을 클릭했을 때 수행할 코드를 작성시켜줍니다.

버튼이 하나일 경우에는 if로 간단하게 하셔도 됩니다. 여러개일 경우에는 위와 같이 switch case로 하시면 됩니다.

 

 

UserPreferences.java

public class UserPreferences extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.user_preferences, rootKey);
    }
}

PreferenceFragmentCompat을 상속한 클래스를 생성합니다.

 

user_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
    <PreferenceCategory
        app:key="notifications_category"
        app:title="Notifications">
        <SwitchPreferenceCompat
            app:key="notifications"
            app:title="알림"/>
        <CheckBoxPreference
            app:title="체크박스"/>
    </PreferenceCategory>
    <PreferenceCategory
        app:key="help_category"
        app:title="Help">
        <Preference
            app:key="feedback"
            app:summary="Report technical issues or suggest new features"
            app:title="Send feedback"/>
    </PreferenceCategory>
</PreferenceScreen>

res 우클릭 - New - Android Resource Directory로 xml 폴더 생성.

xml 폴더 우클릭해서 root element를 PreferenceScreen로 해서 xml파일을 생성.

스위치, 체크박스 등 설정이 가능하고, 카테고리로 지정해서 묶을수도 있습니다.

 

PreferencesActivity.java

public class PreferencesActivity extends AppCompatActivity {

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

AppCompatActivity를 상속한 클래스를 생성합니다.

 

preferences.xml

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

    <fragment
    	android:id="@+id/settings_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="클래스명"/>

</FrameLayout>

res/layout에 xml파일을 생성합니다.

FrameLayout에 fragment를 만들고 android:name에 PreferenceFragmentCompat을 상속받은 클래스명을 입력해주시면 됩니다.

(settings_container로 id 설정 안해주시면 에러 발생합니다.)

 

<activity android:name=".PreferencesActivity"/>

manifest에 activity를 추가해줍니다. AppCompatActivity가 상속된!

 

 

preferences 파일이 여러개여서 혼동이 올 수 있으니 유의하세요.



Intent로 화면 전환, 데이터 전달


다른 액티비티로 이동을 하거나, 데이터 전달을 하려고 경우에 Intent를 사용하면 됩니다.

 

1. 화면 이동

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getBaseContext(), NextActivity.class);
                startActivity(intent);
            }
        });

위는 버튼을 눌렀을 때 다른 Activity로 이동하는 액티비티입니다.

Intent 생성 후 new Intent 안에 첫 번째 인자(현재Activity의 content), 두 번째 인자(이동하려는 Activity.class)로 작성해주시면 됩니다.

그리고 startActivity에 intent를 담아 실행시켜주시면 해당버튼을 클릭했을 때 원하는 Activity로 이동할 수 있습니다.

 

2. 데이터 전달

- 데이터 전달

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getBaseContext(), NextActivity.class);
                intent.putExtra("name", "chocolate");
                intent.putExtra("amount", 20);
                startActivity(intent);
            }
        });

화면 이동 코드에서 putExtra만 추가해주면 됩니다.

putExtra 첫 번째 인자에는 키값을 원하는 String값으로 설정해주고, 두 번째 인자에는 전달할 값을 적어줍니다.

 

- 데이터 수신

Intent intent = getIntent();
String name = intent.getExtra().getString("name");
String amount = intent.getExtra().getInt("amount");

전달된 데이터를 받을 때는 getIntent()로 받아옵니다.

String의 경우에는 intent.getExtra().getString("키값");

int의 경우에는 intent.getExtra().getInt("키값"); 으로 값을 받아와 변수에 담아주면 됩니다.



테두리 설정하기


drawable - New - Drawable Resource File 클릭.

 

Root element에 layer-list 입력하고, 원하는 파일명 작성 후 OK.

 

up_down_border.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:top="2dp"
        android:left="-3dp"
        android:right="-3dp"
        android:bottom="2dp">
        <shape android:shape="rectangle" >
            <stroke
                android:width="2dp"			// 테두리 두께
                android:color="#aaa" />		// 테두리색

            <solid android:color="#FFF" />	// 배경색
        </shape>
    </item>
</layer-list>

top, left, right, bottom에 있는 값들은 선의 위치입니다. - 값을 이용해 원하는 테두리만 표시되도록 설정이 가능합니다.

 

android:background="@drawable/up_down_border"

완성한 xml파일은 background에서 사용하시면 됩니다.



 

ConstraintLayout Widget 에러

This view is not constrained vertically...


 

This view is not constrained vertically: at runtime it will jump to the top unless you add a vertical constraint 에러가 발생하는 경우

Layout으로 ConstraintLayout을 사용하고 있을 겁니다.

 

이 경우에 Design이나 Code에서 제약(Constraint)를 설정해줘야 합니다.

 

Constraint를 설정해주시면 에러가 사라집니다~



android:windowSoftInputMode="adjustResize"


 

Manifest.xml파일 내부에 activity태그 안에 android:windowSoftInputMode="adjustResize"를 만들어 작성해주시면 됩니다.

 

adjustResize는 키보드가 올라올 때 EditText를 resize해서 키보드에 가려지는 UI가 없도록 만들어 줍니다.



코드가 바로 실행되지 않고 약간의 시간이 필요한 경우 Handler를 이용해서 딜레이를 설정할 수 있습니다.

 

new Handler().postDelayed(new Runnable()
{
	@Override
	public void run()
	{
		// 딜레이가 끝난 후 실행할 코드 작성.
	}
}, 1000);// 딜레이 시간 설정. (1초 = 1000)

 



위와 같은 에러가 발생할 경우

build.gradle(module:app)에 코드를 추가시켜주면 됩니다.

defaultConfig{
	vectorDrawables.useSupportLibrary = true
}​

'안드로이드 > Android 에러' 카테고리의 다른 글

[Android] ConstraintLayout Widget 에러  (0) 2020.08.31

+ Recent posts