728x90

새로운 기능을 계속 테스트하다보니 로그인 화면 만드는 것을 자주 시도해야 해서 너무 귀찮아서 가장 기본적인 폼을 만드는 1단계 코드만 작성해서 오픈한다. 저같은 초보자, 입문자에게는 도움이 될 것으로 본다.


테스트 환경

Android Studio 3.2, Android 8.0


이 코드는 서버와 통신하는 기능을 배제한 코드다.


LoginForm.zip



dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:recyclerview-v7:27.1.1' // ListView 개선 버전
    implementation 'com.android.support:cardview-v7:27.1.1'
    implementation 'gun0912.ted:tedpermission:2.0.0'
}


 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.dcdroid.chatapp">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Login">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


 package com.dcdroid.chatapp;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;

import java.util.ArrayList;

public class Login extends AppCompatActivity {
    private static String TAG = "LoginActivity";
    Context context;
    public SharedPreferences pref;
    EditText etId;
    EditText etPw;
    String loginID;
    String loginPW;
    CheckBox autologin;

    public static int OVERLAY_PERMISSION_REQ_CODE = 1234;

    PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {
            initView();
        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            Toast.makeText(Login.this, "권한 허용을 하지 않으면 서비스를 이용할 수 없습니다.", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        context = this.getBaseContext();

        // 네트워크 연결상태 체크
        if (NetworkConnection() == false) NotConnected_showAlert();
        checkPermissions();
    }

    private void checkPermissions() {
        if (Build.VERSION.SDK_INT >= 23) { // 마시멜로(안드로이드 6.0) 이상 권한 체크
            TedPermission.with(context)
                    .setPermissionListener(permissionlistener)
                    .setRationaleMessage("앱을 이용하기 위해서는 접근 권한이 필요합니다")
                    .setDeniedMessage("앱에서 요구하는 권한설정이 필요합니다...\n [설정] > [권한] 에서 사용으로 활성화해주세요.")
                    .setPermissions(new String[]{
                            android.Manifest.permission.READ_PHONE_STATE,
                            android.Manifest.permission.CALL_PHONE,  // 전화걸기 및 관리
                            android.Manifest.permission.WRITE_CONTACTS, // 주소록 액세스 권한
                            android.Manifest.permission.READ_EXTERNAL_STORAGE,
                            android.Manifest.permission.WRITE_EXTERNAL_STORAGE // 기기, 사진, 미디어, 파일 엑세스 권한
                            //android.Manifest.permission.RECEIVE_SMS //, // 문자 수신
                            //android.Manifest.permission.CAMERA
                    })
                    .check();

        } else {
            initView();
        }
    }

    public void checkPermissionOverlay() {
        if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) {
            Intent intentSettings = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityForResult(intentSettings, OVERLAY_PERMISSION_REQ_CODE);
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (!Settings.canDrawOverlays(this)) {
                // You don't have permission
            } else {
                Toast.makeText(this, "오버레이 권한 없이는 발신자정보 팝업을 이용할 수 없습니다...", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void initView() {
        checkPermissionOverlay(); // 오버레이 권한 설정

        findViewById(R.id.setting).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (Build.VERSION.SDK_INT >= 26) {
                    NonSecretApp_Setting(); // 출처를 알 수 없는 앱 설정 화면 띄우기
                } else {
                    startActivity(new Intent(android.provider.Settings.ACTION_SECURITY_SETTINGS));
                }
            }
        });

        etId = (EditText) findViewById(R.id.login_id_edit);
        etPw = (EditText) findViewById(R.id.login_pw_edit);
        autologin = (CheckBox) findViewById(R.id.autologinchk);

        pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        String savedID = pref.getString("id", "");
        etId.setText(savedID);
        String passwd = pref.getString("pw", ""); // 보안상 여기에 적으면 안되는 코드지만 테스트 목적이라...
        etPw.setText(passwd);
        if (!pref.getString("id", "").equals(""))
            etPw.requestFocus();
        String chk1 = pref.getString("autologin", "");
        if (chk1.equals("checked"))
            autologin.setChecked(true);

        if (!pref.getString("loginID", "").equals("")) etPw.requestFocus();

        Button submit = (Button) findViewById(R.id.login_btn);
        submit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginID = etId.getText().toString().trim();
                loginPW = etPw.getText().toString().trim();
                if (loginID != null && !loginID.isEmpty() && loginPW != null && !loginPW.isEmpty()) {
                    // 여기에 적을 코드는 아닌데 테스트 목적이다보니 귀차니즘으로 여기에 적음
                    pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
                    SharedPreferences.Editor editor = pref.edit();

                    editor.putString("id", loginID);
                    editor.putString("pw", loginPW);
                    editor.putString("autologin", "checked"); // 로그인되면 무조건 자동로그인 처리
                    editor.commit();
                    // 실제 로그인할 함수 실행 (아이디와 패스워드 정보를 넘겨줌)
                    // 블로그에 오픈된 코드를 찾아서 같이 활용하면 서버와의 통신이 가능
                    new UserLoginTask().execute(loginID,loginPW);
                }
            }
        });
    }

    private void NonSecretApp_Setting() {
        if (Build.VERSION.SDK_INT >= 26) { // 출처를 알 수 없는 앱 설정 화면 띄우기
            PackageManager packageManager = getPackageManager();
            boolean isTrue = packageManager.canRequestPackageInstalls();

            if (!packageManager.canRequestPackageInstalls()) {
                AlertDialog.Builder b = new AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog);
                b.setTitle("알림");
                b.setMessage("보안을 위해 스마트폰 환경설정의 '앱 설치 허용'을 설정해 주시기 바랍니다.설정화면으로 이동하시겠습니까?");
                b.setCancelable(false);
                b.setPositiveButton("설정하기", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                        intent.setData(Uri.parse("package:" + getPackageName()));
                        startActivity(intent);
                    }
                });

                b.setNegativeButton("건너띄기", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
                b.show();
            }
        }
    }

    private void NotConnected_showAlert() {
        AlertDialog.Builder builder = new AlertDialog.Builder(Login.this);
        builder.setTitle("네트워크 연결 오류");
        builder.setMessage("사용 가능한 무선네트워크가 없습니다.\n" + "먼저 무선네트워크 연결상태를 확인해 주세요.")
                .setCancelable(false)
                .setPositiveButton("확인", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        finish(); // exit
                        //application 프로세스를 강제 종료
                        android.os.Process.killProcess(android.os.Process.myPid());
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();

    }

    private boolean NetworkConnection() {
        int[] networkTypes = {ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI};
        try {
            ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            for (int networkType : networkTypes) {
                NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
                if (activeNetwork != null && activeNetwork.getType() == networkType) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    private class UserLoginTask  extends AsyncTask<String, Void, Boolean> {
        // String 으로 값을 전달받은 값을 처리하고, Boolean 으로 doInBackground 결과를 넘겨준다.
        @Override
        protected Boolean doInBackground(String... strings) {
            return null;
        }
    }
}


나머지는 첨부파일 받아서 이용하면 된다.


AsyncTask 함수는 http://link2me.tistory.com/1516 참조.

AsyncTask 대신에 Volley 라이브러리 사용하는 법은 http://link2me.tistory.com/1533 참조



도움이 되셨다면 000 해 주세요. 좋은 글 작성에 큰 힘이 됩니다.

블로그 이미지

Link2Me

,