Merhaba,


Bu yazı serisinde Android Studio, Socket.io ve Mysql ile online oyun yapımından bahsediyorum.


Videolu anlatım için buraya tıklayınız.
Serinin ilk yazısı için buraya tıklayınız.
Serinin üçüncü yazısı için buraya tıklayınız.


Serinin bu ikinci yazısında login ekranını tasarlayıp dinamik olarak çalıştırıyoruz. Ayrıca gerekli renk, string gibi tanımlamaları yapıyoruz.


Android Studio projesi üzerinde;


res/values klasörü içindeki colors.xml dosyasını açarak proje boyunca gerekli renk tanımlamalarını yapıyoruz:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="available">#27ae60</color>
    <color name="busy">#c0392b</color>
    <color name="white">#FFF</color>
</resources>


res/values klasörü içindeki strings.xml dosyasını açarak proje boyunca gerekli string tanımlamalarını yapıyoruz:

<resources>
    <string name="app_name">Online Math Game</string>

    <string name="text_welcome">Hoşgeldin yusufborucu</string>
    <string name="text_online_users">Online kullanıcılar</string>
    <string name="text_player">aliveli</string>
    <string name="text_username">Yoksa oluşturulacak.</string>
    <string name="text_password">Unutursanız geri dönüşü yok.</string>
    <string name="text_time">10</string>
    <string name="text_question">15 + 20 = ?</string>
    <string name="text_score">0</string>
    <string name="text_result">Oyunu yusufborucu kazandı!</string>
    <string name="text_result_draw">Oyun berabere bitti!</string>
    <string name="text_rank">1</string>

    <string name="hint_username">Kullanıcı adı</string>
    <string name="hint_password">Parola</string>
    <string name="hint_answer">Cevap</string>

    <string name="button_login">Giriş Yap</string>
    <string name="button_send">Gönder</string>
    <string name="button_home">Anasayfa</string>
</resources>


res/values klasörü içindeki styles.xml dosyasını açarak uygulama temasını NoActionBar olarak tanımlıyoruz:

...
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...


activity_login.xml dosyasını açıyoruz ve içeriğini şu şekilde doldurarak login ekranı tasarımını yapmış oluyoruz:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LoginActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/arbutus"
        android:text="@string/app_name"
        android:textAllCaps="false"
        android:textColor="@color/colorPrimary"
        android:textSize="25sp"
        app:layout_constraintBottom_toTopOf="@+id/etUsername"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/etUsername"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="@string/hint_username"
        android:inputType="textPersonName"
        android:fontFamily="@font/arbutus"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/text_username"
        android:fontFamily="@font/arbutus_slab"
        app:layout_constraintStart_toStartOf="@+id/etUsername"
        app:layout_constraintTop_toBottomOf="@+id/etUsername" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPassword"
        android:hint="@string/hint_password"
        android:fontFamily="@font/arbutus"
        android:layout_marginTop="50dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etUsername" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/text_password"
        android:fontFamily="@font/arbutus_slab"
        app:layout_constraintStart_toStartOf="@+id/etPassword"
        app:layout_constraintTop_toBottomOf="@+id/etPassword" />

    <Button
        android:id="@+id/bLogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:background="@color/colorPrimary"
        android:text="@string/button_login"
        android:fontFamily="@font/arbutus"
        android:textAllCaps="false"
        android:textColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etPassword" />

</androidx.constraintlayout.widget.ConstraintLayout>


LoginActivity.kt dosyasını açarak şu kodları yazıyoruz ve girilen kullanıcı adı ve parolanın server tarafına emit edilmesini sağlıyoruz:

...
lateinit var socket: Socket

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_login)

    socket = App.socket

    bLogin.setOnClickListener {
        val username = etUsername.text.toString()
        val password = etPassword.text.toString()
        val user = JSONObject()
        user.put("username", username)
        user.put("password", password)
        socket.emit("user_connect", user)
    }
...


Node.js projesi üzerinde;


server.js dosyasını açarak users adında bir dizi oluşturuyoruz. Client tarafından gelen user_connect emit'ini karşılıyoruz:

...
let users = [];

io.on('connection', socket => {

    socket.on('user_connect', (data) => {
        connection.query("SELECT id FROM users WHERE username = '" + data.username + "'", (error, user) => {
            if (user.length > 0) {
                connection.query("SELECT id FROM users WHERE username = '" + data.username + "' AND password = '" + data.password + "'", (error, user) => {
                    if (user.length > 0) {
                        let userObj = { id: socket.id, username: data.username, status: true };
                        users.push(userObj);
                        io.to(socket.id).emit('user_connect', data.username);                        
                    } else {
                        io.to(socket.id).emit('wrong_password', 'Parola yanlış.');
                    }        
                });
            } else {
                connection.query("INSERT INTO users (username, password) VALUES ('" + data.username + "', '" + data.password + "')");
                let userObj = { id: socket.id, username: data.username, status: true };
                users.push(userObj);
                io.to(socket.id).emit('user_connect', data.username);  
            }
        });        
    });

Burada yaptığımız işlemler;

  • Client tarafından gelen kullanıcı adı veritabanında bulunan users tablosunda mevcutsa kullanıcı adı ve parolaya göre kontrol et. Parola yanlışsa wrong_password emit'i yap. Parola doğruysa bir userObj oluşturup users dizisine ekle ve user_connect emit'i yap.
  • Kullanıcı adı veritabanında mevcut değilse gelen kullanıcı adı ve parola ile yeni kayıt oluştur. Sonrasında yine aynı şekilde userObj oluşturup users dizisine ekle ve user_connect emit'i yap.


Android Studio projesi üzerinde;


LoginActivity.kt dosyasını açarak server tarafından gelen user_connect ve wrong_password emit'lerini karşılıyoruz:

...
socket.on("user_connect") {
    runOnUiThread {
        run {
            val username = it[0].toString()

            val preferences = getSharedPreferences("app", Context.MODE_PRIVATE)
            val editor = preferences.edit()
            editor.putString("username", username)
            editor.apply()

            val intent = Intent(applicationContext, MainActivity::class.java)
            startActivity(intent)
            finish()
        }
    }
}

socket.on("wrong_password") {
    runOnUiThread {
        run {
            Toast.makeText(applicationContext, it[0].toString(), Toast.LENGTH_SHORT).show()
        }
    }
}

Burada yaptığımız işlemler;

  • user_connect kısmında gelen kullanıcı adı verisini sharedPreferences üzerinde kaydet ve Intent yardımıyla MainActivity ekranına geçiş yap.
  • wrong_password kısmında gelen veriyi Toast yardımıyla ekrana yazdır.


Bir sonraki yazıda görüşmek üzere...