Android Login-Register Ekran Yapımı (PHP, MySQL ve SQLite kullanarak)

Android uygulamalarda önemli bir yere sahip olan login ve register ekranları birçok projelerde kullanılmaktadır. Projelerde önemli bir yere sahip olan bu yapıları bir kere kurguladığınız takdirde farklı farklı birçok projede gerçekleştirebilirsiniz. Makalemizde register sonrasında tutulacak olan kayıtlara ait verileri PHP ve MySQL kullanarak kayıt altına alacağız. Bunu gerçekleştirirken RESTful API yapısını kullanacağız. Mobil arayüz ile etkileşimi sağlamak amacıylada Android uygulamamızda SQLite sistemini kurgulayacağız.

Daha önce sizlerle paylaştığımız "Android'de örnek login ve registration sayfası dizaynı" başlıklı makalemizde uygulama arayüzünün nasıl oluşturulduğunu sizlerle paylaşmıştık. Bu makalemizde arayüzü sadece design olarak degil, fonksiyonel hale getirmeye başlayacağız.

API (Application Programming Interface)

Mobil uygulama ile veri alışverişini sorunsuz şekilde gerçekleştirmek, gelen verilerin MySQL veritabanına kaydedilmesini sağlamak amacıyla Rest API kurgusunu hazırlamamız gerekecektir. API, bu tip verilerin karşılıklı aktığı sistemlerde mobil uygulama ile sunucu arasında ortak bir protokol olarak da isimlendirilebilir. Biz bu makalede PHP ve MySQL kullanarak bu işlemi gerçekleştireceğiz. Eğer siz Nodejs veya Ruby konusunda daha yetkinseniz bunları da kullanmanızda herhangi bir mahsur yoktur. Hazırlayacağımız API yapacağı işlemler şu şekildedir;

  • GET/POST metodları üzerinden API çağrılarının alınması
  • Veritabanına yeni kullanıcı kaydının oluşturulması
  • Veritabanında kayıtlı olan kullanıcının bilgilerinin çekilmesi
  • API cevaplarının JSON formatta iletilmesi

WAMPServer Kurulumu

Öncelikle server tarafının çalışacağı webserverin belirlenmesi ve kurulması gerekmektedir. Projemizde pratik ve hızlı bir çözüm sunacağını düşündüğümüz WampServer'i tercih edeceğiz. Wampserver kurulumu ile birlikte Apache, PHP ve MySQL kurulumlarını tek seferde gerçekleştirmiş oluyoruz. Wampserver kurulumu için www.wampserver.com/en/ linkine tıklayınız. Programı indirip kurulumu gerçekleştirdikten sonra Start ⇒ All Programs ⇒ WampServer ⇒ StartWampServer seçeneğinden Wampserveri başlatabilirsiniz. Eğer MAC bilgisayarınız varsa WAMP yerine MAMP Server kurulumunu gerçekleştirebilirsiniz. MAMP Servere erişmek için https://www.mamp.info/en/downloads/ linkine tıklayınız.

Artık projenin sunucu tarafını http://localhost üzerinden test edebilirsiniz. Veritabanına erişim içinse http://localhost/phpmyadmin linkinden yararlanabilirsiniz.

Veritabanı İşlemleri

WAMPServer kurulumu sonrasında artık MySQL veritabanına erişimi kolaylıkla gerçekleştirebiliriz. Burada http://localhost/phpmyadmin linki üzerinden veritabanına erişim sağlayabilirsiniz. Öncelikle ornek_proje adında bir veritabanı oluşturalım. Sonrasında da bu veritabanına içerisinde kullanicilar adında bir tablo oluşturalım.

CREATE DATABASE ornek_proje
USE ornek_proje
 
CREATE TABLE kullanicilar(
   id int(11) primary key auto_increment,
   unique_id varchar(23) not null unique,
   name varchar(50) not null,
   email varchar(100) not null unique,
   encrypted_password varchar(80) not null,
   salt varchar(10) not null,
   created_at datetime,
   updated_at datetime null
);

PHP Projesi

MYSQL üzerinde veritabanı ve tabloları oluşturduktan sonra PHP dili kullanılarak API kısmının yazılmasında sıra. Burada öncelikle WAMPServeri kurduğunuz dizine gidip www dizini altında ornek_proje baslıgında bir dizin oluşturun. Bu dizin içerisine API yi hazırlarken kullanacağınız PHP kodlamalarını yerleştireceğiz. Projeye ait klasör yapısı aşağıdaki şekilde olacaktır.

Projede kullanılan PHP sınıfları;

config.php: Veritabanına bağlantısında kullanılacak config bilgilerin setlendiği sınıf.

db_connect.php: Veritabanı bağlantısının sağlandığı sınıf.

db_functions.php: Veritabanı üzerinde gerçekleştirilecek olan işlemlerde kullanılan sınıf.

login.php: Android uygulamadan login olmaya çalışılırken kullanılan sınıf.

register.php: Android uygulamadan register olmaya çalışırken kullanılan sınıf.

Projede config.php dosyasının içerisine aşağıdaki kodlamayı yapıştıralım.

<?php
define("DB_HOST", "localhost");
define("DB_USER", "root");
define("DB_PASSWORD", "rootsifre");
define("DB_DATABASE", "ornek_proje");
?>

Bu dosyada DB_USER ve DB_PASSWORD alanlarının karşısına veritabanını oluştururken kullandığınız kullanıcı adı ve şifre bilgilerini yerleştiriniz.

Sonrasında db_connect.php dosyasının içerisine aşağıdaki kodlamayı yapıştıralım.

<?php
class db_connect {
    private $conn;
 
    public function connect() {
        require_once 'include/config.php';
         
        $this-?>conn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE);
         
        return $this-?>conn;
    }
}
?>

Şimdi veritabanı işlemlerini gerçekleştireğimiz db_functions.php dosyasını oluşturup içerisine aşağıdaki kodlamaları yapıştıralım. Bu sınıf içerisinde tanımlanan fonksiyonlar; yeni kullanıcı oluşturulması veya mevcut olan kullanıcıların veritabanından getirilmesinde kullanılacaktır. Sınıf içerisinde tanımlanan uniqid('', true) metodu ile her kullanıcıya uniq bir id tanımlanması hedeflenmektedir. base64_encode metodu ile de kullanıcı şifresinin hashlenmesi sağlanmaktadır. Burada güvenliği üst seviyede tutmak adına salt verisi ve hashlenmiş şifrelerin veritabanında tutulması sağlanmaktadır.

<?php

class db_functions {
 
    private $conn;
 
    function __construct() {
        require_once 'db_connect.php';
        $db = new db_connect();
        $this->conn = $db->connect();
    }
 
    function __destruct() {
         
    }
 
    public function storeUser($name, $email, $password) {
        $uuid = uniqid('', true);
        $hash = $this->hashSSHA($password);
        $encrypted_password = $hash["encrypted"];
        $salt = $hash["salt"];
 
        $stmt = $this->conn->prepare("INSERT INTO kullanicilar(unique_id, name, email, encrypted_password, salt, created_at) VALUES(?, ?, ?, ?, ?, NOW())");
        $stmt->bind_param("sssss", $uuid, $name, $email, $encrypted_password, $salt);
        $result = $stmt->execute();
        $stmt->close();
 
        if ($result) {
            $stmt = $this->conn->prepare("SELECT * FROM kullanicilar WHERE email = ?");
            $stmt->bind_param("s", $email);
            $stmt->execute();
            $user = $stmt->get_result()->fetch_assoc();
            $stmt->close();
 
            return $user;
        } else {
            return false;
        }
    }

    public function getUserByEmailAndPassword($email, $password) {
 
        $stmt = $this->conn->prepare("SELECT * FROM kullanicilar WHERE email = ?");
 
        $stmt->bind_param("s", $email);
 
        if ($stmt->execute()) {
            $user = $stmt->get_result()->fetch_assoc();
            $stmt->close();
 
            $salt = $user['salt'];
            $encrypted_password = $user['encrypted_password'];
            $hash = $this->checkhashSSHA($salt, $password);
            if ($encrypted_password == $hash) {
                return $user;
            }
        } else {
            return NULL;
        }
    }
 
    public function isUserExisted($email) {
        $stmt = $this->conn->prepare("SELECT email from kullanicilar WHERE email = ?");
 
        $stmt->bind_param("s", $email);
 
        $stmt->execute();
 
        $stmt->store_result();
 
        if ($stmt->num_rows > 0) {
            $stmt->close();
            return true;
        } else {
            $stmt->close();
            return false;
        }
    }
 
    public function hashSSHA($password) {
        $salt = sha1(rand());
        $salt = substr($salt, 0, 10);
        $encrypted = base64_encode(sha1($password . $salt, true) . $salt);
        $hash = array("salt" => $salt, "encrypted" => $encrypted);
        return $hash;
    }
 
    public function checkhashSSHA($salt, $password) {
        $hash = base64_encode(sha1($password . $salt, true) . $salt);
        return $hash;
    }
 
}


?>

Yeni Kullanıcı Kaydı

Yukarıda tanımladığımız Php sınıfı ile birlikte artık ihtiyacımız olan tüm yapılar hazır durumdadır. Şimdi birlikte yeni kullanıcı kaydı oluşturacak sınıfı yazalım. Kullanıcı kaydında name, email ve password gibi alanları kullanarak sistemimizi hazırlayalım. Bu veriler Android uygulamamız üzerinden POST metodu ile iletilecektir.

Şimdi Php projemizin olduğu dizinde register.php isminde dosya oluşturup aşağıdaki kodlamayı içerisine yapıştıralım.

<?php

require_once 'include/db_functions.php';
$db = new db_functions();
 
$response = array("error" => FALSE);
 
if (isset($_POST['name']) && isset($_POST['email']) && isset($_POST['password'])) {
 
    $name = $_POST['name'];
    $email = $_POST['email'];
    $password = $_POST['password'];
 
    // kullanıcı sistemde kayıtlı bir email ile hesap oluşturuyormu?
    if ($db->isUserExisted($email)) {
        // kullanıcı sistemde kayıtlı ise
        $response["error"] = TRUE;
        $response["error_msg"] = $email. " maili ile ilişkili bir hesap sistemde bulunmaktadır";
        echo json_encode($response);
    } else {
        // yeni kullanıcı oluşturalım
        $user = $db->storeUser($name, $email, $password);
        if ($user) {
            // kullanıcı başarılı şekilde kayıt edildi
            $response["error"] = FALSE;
            $response["uid"] = $user["unique_id"];
            $response["user"]["name"] = $user["name"];
            $response["user"]["email"] = $user["email"];
            $response["user"]["created_at"] = $user["created_at"];
            $response["user"]["updated_at"] = $user["updated_at"];
            echo json_encode($response);
        } else {
            // kullanıcı sisteme kayıt edilemedi
            $response["error"] = TRUE;
            $response["error_msg"] = "Hesap oluşturulurken bilinmedik bir sorun ile karşılaşıldı!";
            echo json_encode($response);
        }
    }
} else {
    $response["error"] = TRUE;
    $response["error_msg"] = "Lütfen zorunlu parametreleri(name, email ve password) eksiksiz girin!";
    echo json_encode($response);
}

?>

Başarılı Kullanıcı Kaydında API den dönecek cevap şu şekilde olacaktır;


{
  "error": false,
  "uid": "44fa7220a2c187.2191519",
  "user": {
    "name": "Yazılım Dersi",
    "email": "[email protected]",
    "created_at": "2021-03-28 15:26:26",
    "updated_at": null
  }
}

Kullanıcı Kaydında sorun yaşandığında API den dönecek cevap şu şekilde olacaktır;


{
    "error": 1,
    "error_msg": "Hesap oluşturulurken bilinmedik bir sorun ile karşılaşıldı!"
}

Kayıtlı kullanıcı kaydında API den dönecek cevap şu şekilde olacaktır;


{
  "success": 0,
  "error": 2,
  "error_msg": "[email protected] maili ile ilişkili bir hesap sistemde bulunmaktadır"
}

Kullanıcı Hesap Girişi

Register işleminin ardından sistemde kayıtlı olan kullanıcıların kontrol edilmesi için Login yani Giriş yapısının kurgulanması gerekecektir. Burada genel olarak kullanılan email ve password ile kullanıcı kontrolünün gerçekleştirilmesidir. İletilecek parametreler POST metodu ile Android uygulama üzerinden iletilecektir. Yapacağımız kontrolde eğer email ve password bilgileri uyuşan herhangi bir kayıt olursa bununla alakalı başarılı sistem cevabını API üzerinden sunacağız. Eğer kayıtlı herhangi bir kullanıcı ile eşleşmiyorsa, o zamanda fail olan mesajımızı API üzerinden ileteceğiz.

Şimdi Php projemizin olduğu dizinde login.php isminde dosya oluşturup aşağıdaki kodlamayı içerisine yapıştıralım.

<?php

require_once 'include/db_functions.php';
$db = new db_functions();
$response = array("error" => FALSE);
 
if (isset($_POST['email']) && isset($_POST['password'])) {
 
    // parametreler
    $email = $_POST['email'];
    $password = $_POST['password'];
 
    // email ve password bilgilerinin kontrol edilmesi
    $user = $db->getUserByEmailAndPassword($email, $password);
 
    if ($user != false) {
        // kullanıcı bulundu
        $response["error"] = FALSE;
        $response["uid"] = $user["unique_id"];
        $response["user"]["name"] = $user["name"];
        $response["user"]["email"] = $user["email"];
        $response["user"]["created_at"] = $user["created_at"];
        $response["user"]["updated_at"] = $user["updated_at"];
        echo json_encode($response);
    } else {
        // bu bilgilerle uyumlu kullanıcı bulunamadı
        $response["error"] = TRUE;
        $response["error_msg"] = "Kullanıcı bilgileri yanlıştır. Lütfen daha sonra tekrar deneyin!";
        echo json_encode($response);
    }
} else {
    // zorunlu parametreleri iletiniz
    $response["error"] = TRUE;
    $response["error_msg"] = "Lütfen zorunlu parametreleri(email ve password) eksiksiz girin!";
    echo json_encode($response);
}
 
?>

Başarılı Kullanıcı Giriş Kontrolünde API den dönecek cevap şu şekilde olacaktır;


{
  "error": false,
  "uid": "44fa7220a2c187.2191519",
  "user": {
    "name": "Yazılım Dersi",
    "email": "[email protected]",
    "created_at": "2021-03-28 15:26:26",
    "updated_at": null
  }
}

Başarısız kullanıcı kontrolünde API den dönecek cevap şu şekilde olacaktır;


{
  "tag": "login",
  "success": 0,
  "error": 1,
  "error_msg": "Kullanıcı bilgileri yanlıştır. Lütfen daha sonra tekrar deneyin!"
}

Şu ana kadar yapılan çalışma ile API kısmındaki düzenlemeler tamamlandı. Şimdi Android uygulamasını yazmaya başlayalım.

Android Uygulaması

Yapacağımız örnek projede json formatta response dönen API çağrısından ( Yukarıda adım adım paylaşılan API) veriyi parse edip login ve register kavramlarını uygulayacağız.

1. File => New Project seçeneğine tıklayalım. Sonrasında açılan ekranda Empty Activity seçeneğini seçip Next butonuna tıklayalım. 
2. Bir sonraki ekranda uygulamanın ismini, paket adını ve kayıt edileceği dizini belirleyelim. İsterseniz uygulamanın adını SampleApp, paket ismi olarak ise info.yazilimdersi.sampleapp olarak belirleyelim.
3. Bu işlemler sonrasında projemiz oluşturuldu. Şimdi sırada projemize ait genel klasörleme ve sınıf yapısının nasıl oluşturacağımız konusunda.
Yukarıda projemize ait ana yapıyı gözlemleyebilirsiniz. Bu sınıfları şimdilik içi boş olacak şekilde oluşturalım. Adım adım içlerine konulacak kodları aşağıda sizlerle paylaşacağız.
4. app dizini altında bulunan build.gradle dosyasını açıp Material Design, Volley ve AppCompat kütüphanelerini ekleyelim.
dependencies {
    .........

    // volley kütüphanesini ekleyelim
    implementation 'com.mcxiaoke.volley:library-aar:1.0.0'
    
    // appcompat ve material kütüphanelerini ekleyelim
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.4.0-alpha01'
}

5. Projemizde internet üzerinden API çağrısı yapılacağı için AndroidManifest.xml dosyasında INTERNET iznini almamız gerekmektedir kullanıcıdan. Ayrıca hazırlanan activitylerin manifest dosyası içerisinde aşağıdaki şekilde tanımlanması gerekecektir.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.yazilimdersi.sampleapp">

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

    <application
        android:name="info.yazilimdersi.sampleapp.core.AppController"
        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=".LoginActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustPan">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".RegisterActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustPan" />
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" />
    </application>

</manifest>

6. Projede tanımlanan labelleri strings.xml dosyası içerisinde tanımlayalım.
<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <string name="app_name">Android Uygulama</string>
    <string name="hint_email">Email</string>
    <string name="hint_password">Şifre</string>
    <string name="hint_name">İsim</string>
    <string name="btn_login">GİRİŞ</string>
    <string name="btn_register">HESAP OLUŞTUR</string>
    <string name="btn_link_to_register">Üye değilmisiniz? Hesap oluşturun.</string>
    <string name="btn_link_to_login">Hesabınız bulunmaktamı? Giriş Yapın.</string>
    <string name="welcome">Merhaba</string>
    <string name="btn_logout">ÇIKIŞ</string>
    <string name="name">İsim</string>
 
</resources>

7. Projede tanımlanan renkleri colors.xml dosyası içerisinde tanımlayalım.
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <color name="bg_login">#26ae90</color>
    <color name="bg_register">#2e3237</color>
    <color name="bg_main">#428bca</color>
    <color name="white">#ffffff</color>
    <color name="input_login">#222222</color>
    <color name="input_login_hint">#999999</color>
    <color name="input_register">#888888</color>
    <color name="input_register_bg">#3b4148</color>
    <color name="input_register_hint">#5e6266</color>
    <color name="btn_login">#26ae90</color>
    <color name="btn_login_bg">#eceef1</color>
    <color name="lbl_name">#333333</color>
    <color name="btn_logut_bg">#ff6861</color>

</resources>
8. Projede app=>core dizini altında AppConfig.java dosyası oluşturup aşağıdaki kodlamayı içerisinde tanımlayalım.
public class AppConfig {
    public static String URL_LOGIN = "http://192.168.1.3/api/login.php";

    public static String URL_REGISTER = "http://192.168.1.3/api/register.php";
}
9. Projede app=>core dizini altında AppController.java dosyası oluşturup aşağıdaki kodlamayı içerisinde tanımlayalım. Bu dosya Application sınıfını extend edip uygulamada tanımlanması gereken genel ayarları belirlemede kullanılacaktır.
import android.app.Application;
import android.text.TextUtils;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;

public class AppController extends Application {

    public static final String TAG = AppController.class.getSimpleName();

    private RequestQueue mRequestQueue;

    private static AppController mInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized AppController getInstance() {
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }

    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }

    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}
10. Projemizde login olan kullanıcının olup olmadığını belirlemek adına hazırlanan SessionManager.java sınıfını aşağıdaki şekilde dolduralım. Hazırlanan sınıf sayesinde daha önceden herhangi bir kullanıcının login olup olmadığı SharedPreferences üzerinden kontrol edilip hazırladığımız fonksiyonlarla check edilecektir.
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;

public class SessionManager {
    private static String TAG = SessionManager.class.getSimpleName();
    SharedPreferences pref;
    Editor editor;
    Context _context;
    int PRIVATE_MODE = 0;

    private static final String PREF_NAME = "AndroidApp";

    private static final String KEY_IS_LOGGEDIN = "isLoggedIn";

    public SessionManager(Context context) {
        this._context = context;
        pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
        editor = pref.edit();
    }

    public void setLogin(boolean isLoggedIn) {
        editor.putBoolean(KEY_IS_LOGGEDIN, isLoggedIn);
        editor.commit();
        Log.d(TAG, "Kullanıcı sisteme giriş yaptı!");
    }

    public boolean isLoggedIn(){
        return pref.getBoolean(KEY_IS_LOGGEDIN, false);
    }
}
11. Projemizde login olan kullanıcı bilgilerinin telefonda tutulması adına hazırlanan SQLiteHandler.java sınıfını aşağıdaki şekilde hazırlayalım. Hazırlanan sınıf sayesinde login olan kullanıcının bilgilerinin SQLiteOpenHelper üzerinden kayıt altına alınması sağlanacaktır.
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import java.util.HashMap;

public class SQLiteHandler extends SQLiteOpenHelper {

    private static final String TAG = SQLiteHandler.class.getSimpleName();
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "androidapp";

    private static final String TABLE_USER = "user";

    private static final String KEY_ID = "id";
    private static final String KEY_NAME = "name";
    private static final String KEY_EMAIL = "email";
    private static final String KEY_UID = "uid";
    private static final String KEY_CREATED_AT = "created_at";

    public SQLiteHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_LOGIN_TABLE = "CREATE TABLE " + TABLE_USER + "("
                + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
                + KEY_EMAIL + " TEXT UNIQUE," + KEY_UID + " TEXT,"
                + KEY_CREATED_AT + " TEXT" + ")";
        db.execSQL(CREATE_LOGIN_TABLE);

        Log.d(TAG, "Veritabanı oluşturuldu");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);
        onCreate(db);
    }

    /**
     * login olan kullanıcı bilgisinin kayıt altına alınması
     * */
    public void addUser(String name, String email, String uid, String created_at) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, name); // isim
        values.put(KEY_EMAIL, email); // email
        values.put(KEY_UID, uid); // email
        values.put(KEY_CREATED_AT, created_at); // oluşturulduğu tarih

        long id = db.insert(TABLE_USER, null, values);
        db.close();

        Log.d(TAG, "New user inserted into sqlite: " + id);
    }

    /**
     * veritabanından kullanıcı bilgilerinin getirilmesi
     * */
    public HashMap<String, String> getUserDetails() {
        HashMap<String, String> user = new HashMap<String, String>();
        String selectQuery = "SELECT  * FROM " + TABLE_USER;

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        cursor.moveToFirst();
        if (cursor.getCount() > 0) {
            user.put("name", cursor.getString(1));
            user.put("email", cursor.getString(2));
            user.put("uid", cursor.getString(3));
            user.put("created_at", cursor.getString(4));
        }
        cursor.close();
        db.close();
        return user;
    }

    /**
     * veritabanında kayıtlı kullanıcıların silinmesi
     * */
    public void deleteUsers() {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_USER, null, null);
        db.close();
    }

}

Login Ekranının Hazırlanması

Projemizde kullanıcının ilk karşılaşacağı ekran olan LoginActivity ekranının hazırlanmasına geldi sıra. AndroidManifest.xml dosyasında default olarak bu Activity nin açılacağını belirlemiştik. res => layout dizini altında activity_login.xml dosyası oluşturup aşağıdaki kodu yapıştıralım.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/white"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="10dp" >



    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical"
        android:paddingLeft="20dp"
        android:paddingRight="20dp" >

        <ImageView
            android:id="@+id/yazilimdersiImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:src="@drawable/logo" />

        <EditText
            android:id="@+id/email"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:background="@color/bg_login"
            android:hint="@string/hint_email"
            android:inputType="textEmailAddress"
            android:padding="10dp"
            android:singleLine="true"
            android:textColor="@color/white"
            android:textColorHint="@color/white" />

        <EditText
            android:id="@+id/password"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:background="@color/bg_login"
            android:hint="@string/hint_password"
            android:inputType="textPassword"
            android:padding="10dp"
            android:singleLine="true"
            android:textColor="@color/white"
            android:textColorHint="@color/white" />


        <Button
            android:id="@+id/btnLogin"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dip"
            android:background="@color/btn_login_bg"
            android:text="@string/btn_login"
            android:textColor="@color/btn_login" />


        <Button
            android:id="@+id/btnLinkToRegisterScreen"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dip"
            android:background="@null"
            android:text="@string/btn_link_to_register"
            android:textAllCaps="false"
            android:textColor="@color/bg_register"
            android:textSize="15dp" />
    </LinearLayout>

</LinearLayout>

Bu arayüz ile ilişkili LoginActivity.java sınıfının içeriğini aşağıdaki şekilde belirleyelim. checkLogin() metodu ile kullanıcının bilgilerini API üzerinden talep edelim.


import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;
import info.yazilimdersi.sampleapp.core.AppConfig;
import info.yazilimdersi.sampleapp.core.AppController;
import info.yazilimdersi.sampleapp.helper.SQLiteHandler;
import info.yazilimdersi.sampleapp.helper.SessionManager;

public class LoginActivity extends Activity {
    private static final String TAG = RegisterActivity.class.getSimpleName();
    private Button btnLogin;
    private Button btnLinkToRegister;
    private EditText inputEmail;
    private EditText inputPassword;
    private ProgressDialog pDialog;
    private SessionManager session;
    private SQLiteHandler db;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        inputEmail = (EditText) findViewById(R.id.email);
        inputPassword = (EditText) findViewById(R.id.password);
        btnLogin = (Button) findViewById(R.id.btnLogin);
        btnLinkToRegister = (Button) findViewById(R.id.btnLinkToRegisterScreen);

        pDialog = new ProgressDialog(this);
        pDialog.setCancelable(false);

        db = new SQLiteHandler(getApplicationContext());
        session = new SessionManager(getApplicationContext());

        // kullanıcının daha önceden giriş yapıp yapmadığını sorgula
        if (session.isLoggedIn()) {
            // kullanıcı daha önceden giriş yapmıştı. MainActivity sınıfına yönlendir
            Intent intent = new Intent(LoginActivity.this, MainActivity.class);
            startActivity(intent);
            finish();
        }

        // giriş butonu
        btnLogin.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                String email = inputEmail.getText().toString().trim();
                String password = inputPassword.getText().toString().trim();

                // herhangi eksik bilgi varmı kontrolü
                if (!email.isEmpty() && !password.isEmpty()) {
                    // kullanıcı girisi
                    checkLogin(email, password);
                } else {
                    // hata mesajı
                    Toast.makeText(getApplicationContext(),
                            "Lütfen tüm bilgileri eksiksiz giriniz!", Toast.LENGTH_LONG)
                            .show();
                }
            }

        });

        btnLinkToRegister.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                Intent i = new Intent(getApplicationContext(),
                        RegisterActivity.class);
                startActivity(i);
                finish();
            }
        });

    }

    /**
     * kullanıcı kontrolü
     * */
    private void checkLogin(final String email, final String password) {
        String tag_string_req = "req_login";

        pDialog.setMessage("Giriş yapılıyor...");
        showDialog();

        StringRequest strReq = new StringRequest(Method.POST,
                AppConfig.URL_LOGIN, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, "Login Response: " + response.toString());
                hideDialog();

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");

                    // hata kodlarının kontrol edilmesi
                    if (!error) {
                        // kullanıcı basarılı sekilde giris yaptı
                        session.setLogin(true);

                        String uid = jObj.getString("uid");

                        JSONObject user = jObj.getJSONObject("user");
                        String name = user.getString("name");
                        String email = user.getString("email");
                        String created_at = user
                                .getString("created_at");

                        // kullanıcı kaydı oluşturuldu
                        db.addUser(name, email, uid, created_at);

                        // MainActivity çağrıldı
                        Intent intent = new Intent(LoginActivity.this,
                                MainActivity.class);
                        startActivity(intent);
                        finish();
                    } else {
                        String errorMsg = jObj.getString("error_msg");
                        Toast.makeText(getApplicationContext(),
                                errorMsg, Toast.LENGTH_LONG).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Login Error: " + error.getMessage());
                Toast.makeText(getApplicationContext(),
                        error.getMessage(), Toast.LENGTH_LONG).show();
                hideDialog();
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("email", email);
                params.put("password", password);

                return params;
            }

        };

        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

    private void showDialog() {
        if (!pDialog.isShowing())
            pDialog.show();
    }

    private void hideDialog() {
        if (pDialog.isShowing())
            pDialog.dismiss();
    }
}

Yapılan düzenleme sonrası login ekranına ait ekran görüntüsü aşağıdaki şekilde olacaktır.

Register Ekranının Hazırlanması

Projemizde yeni kullanıcı kaydının oluşturulmasında kullanılacak olan RegisterActivity ekranının hazırlanmasına geldi sıra. Kullanıcıya ait name, email ve password bilgilerinin bu arayüz üzerinden girilmesi gerekmektedir.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/white"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="10dp" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical"
        android:paddingLeft="20dp"
        android:paddingRight="20dp" >

        <ImageView
            android:id="@+id/yazilimdersiImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:src="@drawable/logo" />

        <EditText
            android:id="@+id/name"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:background="@color/input_register_bg"
            android:hint="@string/hint_name"
            android:padding="10dp"
            android:singleLine="true"
            android:inputType="textCapWords"
            android:textColor="@color/white"
            android:textColorHint="@color/white" />

        <EditText
            android:id="@+id/email"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:background="@color/input_register_bg"
            android:hint="@string/hint_email"
            android:inputType="textEmailAddress"
            android:padding="10dp"
            android:singleLine="true"
            android:textColor="@color/white"
            android:textColorHint="@color/white" />

        <EditText
            android:id="@+id/password"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:background="@color/input_register_bg"
            android:hint="@string/hint_password"
            android:inputType="textPassword"
            android:padding="10dp"
            android:singleLine="true"
            android:textColor="@color/white"
            android:textColorHint="@color/white" />

        <Button
            android:id="@+id/btnRegister"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dip"
            android:background="#ea4c88"
            android:text="@string/btn_register"
            android:textColor="@color/white" />

        <Button
            android:id="@+id/btnLinkToLoginScreen"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dip"
            android:background="@null"
            android:text="@string/btn_link_to_login"
            android:textAllCaps="false"
            android:textColor="@color/bg_register"
            android:textSize="15dp" />
    </LinearLayout>

</LinearLayout>

Bu arayüz ile ilişkili RegisterActivity.java sınıfının içeriğini aşağıdaki şekilde belirleyelim. registerUser() metodu ile yeni kullanıcı kaydını gerçekleştirelim.

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import info.yazilimdersi.sampleapp.R;
import info.yazilimdersi.sampleapp.core.AppConfig;
import info.yazilimdersi.sampleapp.core.AppController;
import info.yazilimdersi.sampleapp.helper.SQLiteHandler;
import info.yazilimdersi.sampleapp.helper.SessionManager;

public class RegisterActivity extends Activity {
    private static final String TAG = RegisterActivity.class.getSimpleName();
    private Button btnRegister;
    private Button btnLinkToLogin;
    private EditText inputFullName;
    private EditText inputEmail;
    private EditText inputPassword;
    private ProgressDialog pDialog;
    private SessionManager session;
    private SQLiteHandler db;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);

        inputFullName = (EditText) findViewById(R.id.name);
        inputEmail = (EditText) findViewById(R.id.email);
        inputPassword = (EditText) findViewById(R.id.password);
        btnRegister = (Button) findViewById(R.id.btnRegister);
        btnLinkToLogin = (Button) findViewById(R.id.btnLinkToLoginScreen);

        pDialog = new ProgressDialog(this);
        pDialog.setCancelable(false);
        session = new SessionManager(getApplicationContext());

        db = new SQLiteHandler(getApplicationContext());

        // kullanıcının daha önceden giriş yapıp yapmadığını sorgula
        if (session.isLoggedIn()) {
            // kullanıcı daha önceden giriş yapmıştı. MainActivity sınıfına yönlendir
            Intent intent = new Intent(RegisterActivity.this,
                    MainActivity.class);
            startActivity(intent);
            finish();
        }

        // hesap oluştur butonu
        btnRegister.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String name = inputFullName.getText().toString().trim();
                String email = inputEmail.getText().toString().trim();
                String password = inputPassword.getText().toString().trim();

                if (!name.isEmpty() && !email.isEmpty() && !password.isEmpty()) {
                    registerUser(name, email, password);
                } else {
                    Toast.makeText(getApplicationContext(),
                            "Lütfen eksiksiz olarak tüm bilgileri giriniz!", Toast.LENGTH_LONG)
                            .show();
                }
            }
        });

        btnLinkToLogin.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                Intent i = new Intent(getApplicationContext(),
                        LoginActivity.class);
                startActivity(i);
                finish();
            }
        });

    }
    
    private void registerUser(final String name, final String email,
                              final String password) {
        String tag_string_req = "req_register";

        pDialog.setMessage("Hesap Oluşturuluyor...");
        showDialog();

        StringRequest strReq = new StringRequest(Method.POST,
                AppConfig.URL_REGISTER, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                hideDialog();

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");
                    if (!error) {
                        String uid = jObj.getString("uid");

                        JSONObject user = jObj.getJSONObject("user");
                        String name = user.getString("name");
                        String email = user.getString("email");
                        String created_at = user
                                .getString("created_at");

                        // users tablosuna icerik ekleyin
                        db.addUser(name, email, uid, created_at);

                        Toast.makeText(getApplicationContext(), "Kullanıcı başarılı şekilde giriş yaptı. Şimdi giriş yapın!", Toast.LENGTH_LONG).show();

                        // login ekranına yönlendir
                        Intent intent = new Intent(
                                RegisterActivity.this,
                                LoginActivity.class);
                        startActivity(intent);
                        finish();
                    } else {
                        // hata mesajı
                        String errorMsg = jObj.getString("error_msg");
                        Toast.makeText(getApplicationContext(),
                                errorMsg, Toast.LENGTH_LONG).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Registration Error: " + error.getMessage());
                Toast.makeText(getApplicationContext(),
                        error.getMessage(), Toast.LENGTH_LONG).show();
                hideDialog();
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("name", name);
                params.put("email", email);
                params.put("password", password);

                return params;
            }

        };

        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

    private void showDialog() {
        if (!pDialog.isShowing())
            pDialog.show();
    }

    private void hideDialog() {
        if (pDialog.isShowing())
            pDialog.dismiss();
    }
}

Yapılan düzenlemeler sonrası register ekranına ait ekran görüntüsü aşağıdaki şekilde olacaktır.

Ana Ekranının Hazırlanması

Uygulamaya giriş yapan kullanıcının karşılaşacağı MainActivity ekranının hazırlanmasını gerçekleştirelim. Bu arayüzde en basitinden giriş yapılmış olan kullanıcıya ait name, email bilgileri görüntülenecektir. Ayrıca kullanıcının logout olmasına imkan sunan bir butonda bu ekranda görüntülenecektir.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/welcome"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textColor="@color/lbl_name"
            android:textSize="24dp" />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="13dp" />

        <Button
            android:id="@+id/btnLogout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dip"
            android:background="@color/btn_logut_bg"
            android:text="@string/btn_logout"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textSize="15dp" />
    </LinearLayout>

</RelativeLayout>

Bu arayüz ile ilişkili RegisterActivity.java sınıfının içeriğini aşağıdaki şekilde belirleyelim. registerUser() metodu ile yeni kullanıcı kaydını gerçekleştirelim.

import info.yazilimdersi.sampleapp.helper.SQLiteHandler;
import info.yazilimdersi.sampleapp.helper.SessionManager;

import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView txtName;
    private TextView txtEmail;
    private Button btnLogout;

    private SQLiteHandler db;
    private SessionManager session;

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

        txtName = (TextView) findViewById(R.id.name);
        txtEmail = (TextView) findViewById(R.id.email);
        btnLogout = (Button) findViewById(R.id.btnLogout);

        db = new SQLiteHandler(getApplicationContext());

        session = new SessionManager(getApplicationContext());

        if (!session.isLoggedIn()) {
            logoutUser();
        }

        // Kullanıcı bilgilerinin veritabanından getirilmesi
        HashMap<String, String> user = db.getUserDetails();

        String name = user.get("name");
        String email = user.get("email");

        // Kullanıcı bilgilerinin ekranda görüntülenmesi
        txtName.setText(name);
        txtEmail.setText(email);

        // Çıkış butonu
        btnLogout.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                logoutUser();
            }
        });
    }

    private void logoutUser() {
        session.setLogin(false);

        db.deleteUsers();

        // login ekranının görüntülenmesi
        Intent intent = new Intent(MainActivity.this, LoginActivity.class);
        startActivity(intent);
        finish();
    }
}

Yapılan düzenlemeler sonrası ana ekrana ait ekran görüntüsü aşağıdaki şekilde olacaktır.

Uygulamanın Test Edilmesi

Hem mobil uygulamaya ait kodlama hem de API ye ait kodlamaları tamamladık. Uygulamanın çalışırlığını test edebilmemiz adına aşağıdaki adımları uygulamanız gerekmektedir;

  • AppConfig.java dosyasında tanımlanan URL_REGISTER ve URL_LOGIN linklerinin cihazınıza ait IP adresi ile değiştirilmesi gerekmektedir. Bunu öğrenmek için bilgisayarınızda komut istemcisini açıp ipconfig komutunu girdiğinizde gelen ekrandaki IPV4 Adres bilgisini kullanmanız gerekecektir.
  • Mobil uygulamayı yüklediğiniz cihazla API nın olduğu bilgisayar aynı network üzerinde olmalıdır.
  • config.php dosyasında username, password ve database alanına veritabanına erişimde kullanılan bilgiler girilmelidir.
comments powered by Disqus