(29-07-2026, Saat: 01:26)emailx45 Adlı Kullanıcıdan Alıntı: Hata ayıklama günlüğü (tam hatayı doğrulamak için): Değişikliği yapmadan önce uygulamanın çökmesine neden olan istisnanın tam yığın izini görmek istiyorsanız, cihazınıza bağlı komut istemi üzerinden `adb logcat` komutunu çalıştırabilirsiniz:
open a CMD console ( if need use as Admin, normally not need ) and try install your app to catch the stack info...
--->> adb logcat -s AndroidRuntime FMX
NOTE: you can use the Android Studio to catch the logs... if you want! just open it and see the "Log" tab
see the attached files: by Gemini for tests ...
Merhabalar
Hocam çok teşekkürler.
Paylaştığınız dökümanı kullanarak Manifest dosyasını düzenledim. Aynı zamanda billing 8.0.0 ile derlemeyi gerçekleştirdim. Uygulama çökmeden açılıyor sorun oluşmuyor. Fakat Rad studio nun FMX.InAppPurchase kütüphanesi kullanılamıyor. Uygulamanın çökmesine o sebeb veriyormuş. Sizin paylaştığınız kütüphaneyi kullanarak bir yapı oluşturdum.
Hocam yapıda bir yere kadar sorunsuz çalışıyor ama sonrasında uygulama hiç tepki vermiyor hata da vermiyor ama satın alma ekranıda gelmiyor maalesef
Kodu altta paylaşıyorum.
{$IFDEF ANDROID}
type
// Bağlantı durumunu dinleyen sınıf
TBillingClientStateListener = class(TJavaLocal, JBillingClientStateListener)
private
FOnConnected: TThreadProcedure;
FOnDisconnected: TThreadProcedure;
public
constructor Create(AOnConnected, AOnDisconnected: TThreadProcedure);
procedure onBillingSetupFinished(billingResult: JBillingResult); cdecl;
procedure onBillingServiceDisconnected; cdecl;
end;
type
// Satın alma sonuçlarını dinleyen zorunlu listener
TPurchasesUpdatedListener = class(TJavaLocal, JPurchasesUpdatedListener)
public
procedure onPurchasesUpdated(billingResult: JBillingResult; purchases: JList); cdecl;
end;
type
// Ürün sorgulama sonucunu dinleyen sınıf
TProductDetailsResponseListener = class(TJavaLocal, JProductDetailsResponseListener)
private
public
constructor Create;
procedure onProductDetailsResponse(billingResult: JBillingResult; productDetailsList: JList); cdecl;
end;
{$ENDIF}
constructor TBillingClientStateListener.Create(AOnConnected, AOnDisconnected: TThreadProcedure);
begin
inherited Create;
FOnConnected := AOnConnected;
FOnDisconnected := AOnDisconnected;
end;
procedure TBillingClientStateListener.onBillingSetupFinished(billingResult: JBillingResult); cdecl;
var
ResCode: Integer;
DebugMsg: string;
begin
if Assigned(billingResult) then
begin
ResCode := billingResult.getResponseCode;
DebugMsg := JStringToString(billingResult.getDebugMessage);
end
else
begin
ResCode := -1; // Bilinmeyen / Nil Yanıt
DebugMsg := 'BillingResult nesnesi nil olarak döndü.';
end;
// ResponseCode = 0 -> OK
if ResCode = TJBillingClient_BillingResponseCode.JavaClass.OK then
begin
TThread.Synchronize(nil,
procedure
begin
if Assigned(FOnConnected) then
FOnConnected();
end);
end
else
begin
TThread.Synchronize(nil,
procedure
begin
ShowMessage('Google Play Servis Bağlantı Hatası Kodu: ' +
ResCode.ToString + ' - ' + DebugMsg);
end);
end;
end;
procedure TBillingClientStateListener.onBillingServiceDisconnected; cdecl;
begin
TThread.Synchronize(nil,
procedure
begin
if Assigned(FOnDisconnected) then
FOnDisconnected();
end);
end;
procedure TPurchasesUpdatedListener.onPurchasesUpdated(billingResult: JBillingResult; purchases: JList); cdecl;
begin
// Kullanıcı bir satın alma yaptığında veya iptal ettiğinde burası tetiklenir
if Assigned(billingResult) and (billingResult.getResponseCode = 0) then
begin
// Satın alma başarılı
end;
end;
procedure TfrmSG_AnaForm.Google_Play_Satin_Alma_Setup_8_0;
var
PendingParamsBuilder: JPendingPurchasesParams_Builder;
PendingParams: JPendingPurchasesParams;
ClientBuilder: JBillingClient_Builder;
begin
FProductDetailsList := TList<JProductDetails>.Create;
ProductListener := TProductDetailsResponseListener.Create;
FPurchasesUpdatedListener := TPurchasesUpdatedListener.Create;
// 1. PendingPurchasesParams
PendingParamsBuilder := TJPendingPurchasesParams_Builder.Wrap(TJPendingPurchasesParams_Builder.JavaClass.init);
PendingParamsBuilder.enableOneTimeProducts;
PendingParams := PendingParamsBuilder.build;
// 2. Client Builder
ClientBuilder := TJBillingClient.JavaClass.newBuilder(TAndroidHelper.Context);
ClientBuilder.setListener(FPurchasesUpdatedListener);
ClientBuilder.enablePendingPurchases(PendingParams);
// 3. BillingClient Oluşturma
FBillingClient := ClientBuilder.build;
// 4. Bağlantı Dinleyicisi
FStateListener := TBillingClientStateListener.Create(
OnBillingConnected,
OnBillingDisconnected
);
// 5. Bağlantıyı Başlat
FBillingClient.startConnection(FStateListener);
end;
procedure TfrmSG_AnaForm.Urunleri_Sorgula;
var
ProductList: JArrayList;
Product: JQueryProductDetailsParams_Product;
QueryParamsBuilder: JQueryProductDetailsParams_Builder;
QueryParams: JQueryProductDetailsParams;
begin
try
if not Assigned(FBillingClient) or not FBillingClient.isReady then
begin
//frmSG_AnaForm.Bildirim_Mesaji('Billing servisi henüz hazır değil!', True, False);
ShowMessage( 'Billing servisi henüz hazır değil!' );
Exit;
end;
ProductList := TJArrayList.JavaClass.init;
// --- ÜRÜN 1 ---
Product := TJQueryProductDetailsParams_Product.JavaClass.newBuilder
.setProductId(StringToJString(frmGoogle_Play_Satis.Elmas_100))
.setProductType(TJBillingClient_ProductType.JavaClass.INAPP)
.build;
ProductList.add(Product);
// --- ÜRÜN 2 ---
Product := TJQueryProductDetailsParams_Product.JavaClass.newBuilder
.setProductId(StringToJString(frmGoogle_Play_Satis.Elmas_500))
.setProductType(TJBillingClient_ProductType.JavaClass.INAPP)
.build;
ProductList.add(Product);
// --- ÜRÜN 3 ---
Product := TJQueryProductDetailsParams_Product.JavaClass.newBuilder
.setProductId(StringToJString(frmGoogle_Play_Satis.Elmas_1000))
.setProductType(TJBillingClient_ProductType.JavaClass.INAPP)
.build;
ProductList.add(Product);
// --- ÜRÜN 4 ---
Product := TJQueryProductDetailsParams_Product.JavaClass.newBuilder
.setProductId(StringToJString(frmGoogle_Play_Satis.Elmas_10000))
.setProductType(TJBillingClient_ProductType.JavaClass.INAPP)
.build;
ProductList.add(Product);
// --- ÜRÜN 5 ---
Product := TJQueryProductDetailsParams_Product.JavaClass.newBuilder
.setProductId(StringToJString(frmGoogle_Play_Satis.Elmas_100000))
.setProductType(TJBillingClient_ProductType.JavaClass.INAPP)
.build;
ProductList.add(Product);
if ProductList.size > 0 then
ShowMessage( 'İçi Dolu ' );
//ShowMessage( 'ürünleri ekledi.' );
// --- QUERY PARAMS OLUŞTURMA (DÜZELTİLEN KISIM) ---
QueryParamsBuilder := TJQueryProductDetailsParams.JavaClass.newBuilder;
// 2. ArrayList'i JList interface'ine Wrap ederek Builder'a veriyoruz
QueryParamsBuilder.setProductList(TJList.Wrap(ProductList));
// 3. Son olarak parametre nesnesini build ediyoruz
QueryParams := QueryParamsBuilder.build;
//ShowMessage( 'paketlendi.' );
// --- SORGULAMA ---
FBillingClient.queryProductDetailsAsync(QueryParams, ProductListener);
//ShowMessage( 'paketler yüklendi.' );
except on e : Exception do
TThread.Synchronize( nil,
procedure
begin
ShowMessage( e.Message );
end );
end;
end;
procedure TfrmSG_AnaForm.OnBillingConnected;
begin
// Bağlantı %100 başarılı!
//Bildirim_Mesaji( 'Google Play Billing v8 Servisine Başarıyla Bağlanıldı! ?', True, True);
Urunleri_Sorgula;
end;
procedure TfrmSG_AnaForm.OnBillingDisconnected;
begin
// Bağlantı koptuğunda çalışır (örneğin Google Play Store güncellenirse)
//ShowMessage('Billing Servis Bağlantısı Koptu, Yeniden Bağlanılıyor...');
// İsterseniz burada SetupBilling; çağırarak tekrar bağlanmayı deneyebilirsiniz.
end;
constructor TProductDetailsResponseListener.Create;
begin
inherited Create;
//ShowMessage( 'Create Tetiklendi.' );
end;
procedure TProductDetailsResponseListener.onProductDetailsResponse(
billingResult: JBillingResult; productDetailsList: JList); cdecl;
var
ResCode: Integer;
DebugMsg: string;
I : Integer;
Details: JProductDetails;
begin
TThread.Queue( nil,
procedure
begin
ShowMessage( 'Veri Geldi ' );
end );
ResCode := billingResult.getResponseCode;
DebugMsg := JStringToString(billingResult.getDebugMessage);
// 1. Durum: Google Başarılı Yanıt Dündü
if ResCode = TJBillingClient_BillingResponseCode.JavaClass.OK then
begin
if Assigned(productDetailsList) and (productDetailsList.size > 0) then
begin
frmSG_AnaForm.FProductDetailsList.Clear;
for I := 0 to productDetailsList.size - 1 do
begin
Details := TJProductDetails.Wrap(productDetailsList.get(I));
frmSG_AnaForm.FProductDetailsList.Add(Details);
end;
frmSG_AnaForm.Bildirim_Mesaji('BAŞARILI: ' + IntToStr(productDetailsList.size) + ' adet ürün yüklendi!', False, False);
end
else
begin
// Google 'OK' dedi ama liste BOMBOŞ döndü!
frmSG_AnaForm.Bildirim_Mesaji('GOOGLE BOŞ DÖNDÜ: IDler eşleşmiyor veya Play Console ürünü aktif değil!', True, False);
end;
end
else
begin
// 2. Durum: Google Hata Döndürdü
frmSG_AnaForm.Bildirim_Mesaji('GOOGLE HATA KODU: ' + IntToStr(ResCode) + ' - ' + DebugMsg, True, False);
end;
end;
procedure TfrmSG_AnaForm.Urun_Satin_Al(const AProductID: string);
var
I: Integer;
TargetDetails: JProductDetails;
ProductParams: JBillingFlowParams_ProductDetailsParams;
ProductParamsList: JArrayList;
FlowParamsBuilder: JBillingFlowParams_Builder;
FlowParams: JBillingFlowParams;
BillingResult: JBillingResult;
begin
try
TargetDetails := nil;
// 1. Daha önce sorgulayıp sakladığımız listeden tıklanan ürünü buluyoruz
ShowMessage( FProductDetailsList.Count.ToString );
for I := 0 to FProductDetailsList.Count - 1 do
begin
if JStringToString(FProductDetailsList[I].getProductId) = AProductID then
begin
TargetDetails := FProductDetailsList[I];
Break;
end;
end;
if not Assigned(TargetDetails) then
begin
frmSG_Store.Bildirim_Mesaji('Ürün detayları henüz yüklenmedi veya bulunamadı!', True, False);
Exit;
end;
// 2. BillingFlowParams için ProductDetailsParams oluşturuyoruz (Billing Library v6/v7/v8 standartı)
ProductParams := TJBillingFlowParams_ProductDetailsParams.JavaClass.newBuilder
.setProductDetails(TargetDetails)
.build;
ProductParamsList := TJArrayList.JavaClass.init;
ProductParamsList.add(ProductParams);
// 3. BillingFlowParams nesnesini derliyoruz
FlowParamsBuilder := TJBillingFlowParams.JavaClass.newBuilder;
FlowParamsBuilder.setProductDetailsParamsList(TJList.Wrap(ProductParamsList));
FlowParams := FlowParamsBuilder.build;
// 4. Google Play Satın Alma Penceresini Açıyoruz!
BillingResult := FBillingClient.launchBillingFlow(TAndroidHelper.Activity, FlowParams);
if BillingResult.getResponseCode <> TJBillingClient_BillingResponseCode.JavaClass.OK then
begin
frmSG_Store.Bildirim_Mesaji('Satın alma başlatılamadı: ' + JStringToString(BillingResult.getDebugMessage), True, False);
end;
except on e : Exception do
ShowMessage( e.Message );
end;
end;
//**************************************************
Hocam burada OnBillingConnected kısmı tatikleniyor Ürün_Sorgula procedure sorunsuz çalışıyor ama google den dönüş olacak procedure TProductDetailsResponseListener.onProductDetailsResponse bu prosedür hiç tetiklenmiyor procedure nin oncreate sini kontrol ettim create oluyor fakat onProductDetailsResponse bu event hiç bir şekilde tetiklenmiyor acaba nerde yanlış yapıyorum bulamadım.