Android 13’e (API 33) hazirlik

Merhaba arkadaşlar;
Bildiğiniz üzere her yıl Google kütüphanelerini yeniliyor. Eski sürüm kod kitaplıklarına artık destek verilmediği için, kodlarınızı güncel tutmanız son derece önemli. Eğer sizde şu projemi bir güncelleyeyim deyip, eski bir projeyi Android Studio’da açmaya çalıştıysanız muhtemelen pek çok hatayla karşılaştınız. Çözmek için internete başvurduğunuzda da bir rüzgar sizi buraya, benim bloguma savurdu. 🙂 Bundan son derece mutluyum. Gelin adım adım hatalarımızı çözelim.

Jetifier Nedir?

Jetifier, AndroidX’i kullanmak için üçüncü taraf bağımlılıklarının taşınmasına yardımcı olur. Jetifier, AndroidX kullanan projelerle uyumlu hale getirmek için bu bağımlılıkların bayt kodunu değiştirecektir. Ancak Jetifier kaynak kodunuzu değiştirmez veya oluşturulan kodunuzu taşımaz.

Bu yüzden bu işlemleri manuel olarak, kendimiz yapmalıyız.

Uygulamanızda Jetifier’ı etkinleştirmek için gradle.properties dosyanıza şu iki satırı ekleyin :

android.useAndroidX=true
android.enableJetifier=true

Proje düzeyinde build.gradle (Project: UygulamaAdi) dosyanızı kontrol edin; (şuna benzer şekilde olmalı)

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.3.1'
        classpath 'com.google.gms:google-services:4.3.10'
        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.0'
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Uygulama düzeyinde build.gradle (Module: UygulamaAdi.app) dosyanızın da bi’ gözden geçmesi gerek, önemli kısımları sizin için vurguladım.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 33
    buildToolsVersion "33.0.0"
    defaultConfig {
        applicationId "com.paketadi.ornekuygulama"
        minSdkVersion 19
        targetSdkVersion 33
        versionCode 1
        versionName "v1.0.0"
        multiDexEnabled true
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        targetCompatibility JavaVersion.VERSION_11
        sourceCompatibility JavaVersion.VERSION_11
    }
    namespace 'com.paketadi.ornekuygulama'
    ndkVersion '24.0.8215888'
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    // Android X
    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.core:core:1.9.0-alpha05'

    implementation "com.google.android.gms:play-services-games-v2:+"        // Google Play Game services
    implementation 'com.google.android.gms:play-services-location:19.0.1'
    implementation 'com.google.android.gms:play-services-ads:21.0.0'        // Google Mobile Ads
    implementation 'com.google.android.gms:play-services-plus:17.0.0'       // Google+
    implementation 'com.google.android.gms:play-services-auth:20.2.0'      // Google Account Login
    implementation 'com.google.android.gms:play-services-base:18.0.1'      // Google Actions, Base Client Library
    implementation 'com.google.android.gms:play-services-identity:18.0.1'  // Google Address API
    implementation 'com.google.android.gms:play-services-nearby:18.2.0'    // Google Nearby

    // Firebase
    implementation platform('com.google.firebase:firebase-bom:30.1.0')
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-crashlytics'

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

Eğer daha önce projenizde “FirebaseCrash” kullandıysanız, burdada bi’ takım değişikler oldu. Gelin bakalım;

// Eski kullanım
FirebaseCrash.logcat(Log.ERROR, getString(R.string.app_name), "Hata Mesaji.");
FirebaseCrash.report(ex);

// Yeni kullanım
FirebaseCrashlytics.getInstance().log("Hata Mesaji");

Tabi Google Sign In için kullandığınız sınıflar da siz ortalıkta yokken değisti. Eskiden şu şekilde tanımlıyorduk;

//-----------------API Ayarı---------------------------------
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(Games.API).addScope(Games.SCOPE_GAMES)
                .build();
        //----------------------------------------------------------

Bu sınıf tamamen kullanımdan kaldırıldı. Bunun yerine artık PlayGamesSdk‘sını kullanacağız;

import com.google.android.gms.games.PlayGames;
import com.google.android.gms.games.PlayGamesSdk;

        // Google Play Games
        PlayGamesSdk.initialize(this);
        GamesSignInClient gamesSignInClient = PlayGames.getGamesSignInClient(this);
        gamesSignInClient.isAuthenticated().addOnCompleteListener(isAuthenticatedTask -> {
            boolean isAuthenticated = (isAuthenticatedTask.isSuccessful() && isAuthenticatedTask.getResult().isAuthenticated());
            if (isAuthenticated) {
                Log.d(TAG, "isAuthenticated : true => Giriş zaten yapıldı !");
                //...
            } else {
                // Play Games Hizmetleriyle entegrasyonunuzu devre dışı bırakın veya
                // oyunculardan oturum açmalarını istemek için bir oturum açma düğmesi gösterin.
                // Üzerine tıklamak, Oyun Oturum Açma İstemcisini çağırmalıdır.
                Log.e(TAG, "isAuthenticated : false => Oturum aciliyor..");
                gamesSignInClient.signIn().addOnSuccessListener(this);
            }
        });

Şimdi nihayet Play Games Hizmetlerini kullanabiliriz, ancak hala başarım kilidi açma (Achievements) ve skor tablosu (Leaderboard) nasıl göstereceğimizi çözmemiz gerekiyor. Hatırlarsanız önceden başarımlar ekranını açmak için şöyle yapıyorduk;

if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        startActivityForResult(Games.Achievements.getAchievementsIntent(mGoogleApiClient), REQUEST_ACHIEVEMENTS);
} else {
        Toast.makeText(getApplicationContext(), R.string.signin_not, Toast.LENGTH_LONG).show();
}

Tahmin edebileceğiniz gibi artık bu yöntem işe yaramayacaktır. Bunun yerine bir showAchievements() isimli bir metot oluşturalım;

public void showAchievements() {
PlayGames.getAchievementsClient(this)
.getAchievementsIntent()
.addOnSuccessListener(new OnSuccessListener<Intent>() {
@Override
public void onSuccess(Intent intent) {
startActivityForResult(intent, RC_ACHIEVEMENT_UI);
}
});
}

İşte oldu şimdi sırada skor tablosunu yani Leaderboard’sı kullanıcıya göstermek var. Önce eski kodumuza bir bakalım;

startActivityForResult(Games.Leaderboards.getAllLeaderboardsIntent(mGoogleApiClient), REQUEST_LEADERBOARD);

Bunu silip yerine showLeaderboard() metodunu çağıralım. Bu metodun kodları ise şu şekilde;

private void showLeaderboard() {
PlayGames.getLeaderboardsClient(this)
.getLeaderboardIntent(getString(R.string.leaderboard_klasik_dookunanlar))
.addOnSuccessListener(new OnSuccessListener<Intent>() {
@Override
public void onSuccess(Intent intent) {
startActivityForResult(intent, RC_LEADERBOARD_UI);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "showLeaderboard() => " + e);
FirebaseCrashlytics.getInstance().recordException(e);
}
});
}

Buraya kadar hazırız. Peki önceden bir olay gerçekleştiğinde kullanıcımıza nasıl başarım açıyorduk?

// Eski kullanım
Games.Achievements.unlock(mGoogleApiClient, getString(R.string.achievement_vote_us));

// Yeni kullanım
PlayGames.getAchievementsClient(this).unlock(getString(R.string.achievement_vote_us));

Bazı başarımlar direk açılmaz, ulaşılması gerekilen hedefler vardır. Artırımlı başarımlar için kodlarımız;

// Eski kullanım
Games.Achievements.increment(MainActivity.mGoogleApiClient, getString(R.string.achievement_x), turSayisi);

// Yeni kullanım
PlayGames.getAchievementsClient(this).increment(getString(R.string.achievement_x), turSayisi);

Oyun bittiğinde kullanıcının oyundaki skorunu güncellemeniz gerekir. Örneğin kullanıcımız yeni bir “High Score” yaptığında bunu Play Games sunucularında da güncellemeliyiz. Gelin bunu nasıl yapacağımıza da bi’ bakalım;

// Eski kullanım
Games.Leaderboards.submitScore(MainActivity.mGoogleApiClient, getString(R.string.leaderboard_kolay), turSayisi);

// Yeni kullanım
PlayGames.getLeaderboardsClient(this).submitScore(getString(R.string.leaderboard_kolay), turSayisi);

Gelelim Google AdSense ayarlarımıza, biraz yorulduk fakat çok az kaldı. Eski kodumuz muhtemelen şu şekildeydi;

// ----------------- Google AdSense ---------------------
        AdView adView = (AdView) this.findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder()
                .addTestDevice("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
                .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                .build();
        if (adView != null) {
            adView.loadAd(adRequest);
        }

Yeni kodumuz ise şu şekilde olacak;

    try {
        mAdView = findViewById(R.id.adView);
        configuration = new RequestConfiguration.Builder().setTestDeviceIds(Arrays.asList(testDeviceIds)).build();
        MobileAds.setRequestConfiguration(configuration);
        MobileAds.initialize(this, new OnInitializationCompleteListener() {
            @Override
            public void onInitializationComplete(InitializationStatus initializationStatus) {
                Log.d(TAG, "MobileAds => onInitializationComplete()");
                mAdView.setAdSize(AdSize.BANNER);
                mAdView.setAdUnitId("ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX");
                adRequest = new AdRequest.Builder().build();
                mAdView.loadAd(adRequest);
            }
        });
    } catch (Exception ex) {
        Log.e(TAG, "Google AdSense => " + ex);
        crashlytics.recordException(ex);
    }

Burda şunlara dikkat etmeniz gerekiyor. Aksi takdirde Google AdMob üyeliğiniz feshedilebilir veya askıya alınabilir.

  1. Google AdMob hesabınıza giriş yapın.
  2. Sol taraftaki menüden Ayarlar -> Test cihazları alanına gidin.
  3. Test Cihazı Ekle butonuna tıklayın.

Eğer hala hata alıyorsanız. Sınıflar, kitaplıklar vs. eski ve yeni sürümü kontrol edebilmeniz için aşağıya bir tablo bırakıyorum. Yapmanız gereken CTRL + R tuşlarına basarak eski kodları yenisi ile değiştirmek.

Android (Eski)Android X
import android.support.v7.app.AppCompatActivity;import androidx.appcompat.app.AppCompatActivity;
import android.support.v4.app.Fragment;import androidx.fragment.app.Fragment;
import android.support.annotation.NonNull;import androidx.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;import com.google.android.material.bottomnavigation.BottomNavigationView;
import android.arch.lifecycle.ViewModelProvider;import androidx.lifecycle.ViewModelProvider;
dependencies
compile fileTree(dir: ‘libs’, include: [‘*.jar’])implementation fileTree(dir: “libs”, include: [“*.jar”])
compile ‘com.android.support.constraint:constraint-layout:2.0.4’implementation ‘androidx.constraintlayout:constraintlayout:2.1.4’
compile ‘com.android.support:appcompat-v7:25.3.1’implementation ‘androidx.appcompat:appcompat:1.4.2’
testCompile ‘junit:junit:4.12’testImplementation ‘junit:junit:4.13.2’
Tablo Android X – Sınıflar ve Kütüphaneler

Buraya kadar okuduğunuz ve benimle kaldığınız için teşekkür ederim. Tekrar görüşmek üzere, hoşçakalın.

👩‍💻 𝕯𝖊𝖛𝖊𝖑𝖔𝖕𝖊𝖗 & 𝕯𝖊𝖘𝖎𝖌𝖓𝖊𝖗 ☕
Yazı oluşturuldu 21

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Benzer yazılar

Aramak istediğinizi üstte yazmaya başlayın ve aramak için enter tuşuna basın. İptal için ESC tuşuna basın.

Üste dön