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.
- Google AdMob hesabınıza giriş yapın.
- Sol taraftaki menüden Ayarlar -> Test cihazları alanına gidin.
- 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 | |
implementation fileTree(dir: “libs”, include: [“*.jar”]) | |
implementation ‘androidx.constraintlayout:constraintlayout:2.1.4’ | |
implementation ‘androidx.appcompat:appcompat:1.4.2’ | |
testImplementation ‘junit:junit:4.13.2’ |
Buraya kadar okuduğunuz ve benimle kaldığınız için teşekkür ederim. Tekrar görüşmek üzere, hoşçakalın.