Android'de OS / Kullanıcı tarafından oyun çökmesine / öldürülmesine ilişkin dosya işlemleri başarısız oldu


13

Oyunum, oyun / uygulama dahili depolama alanındaki bir dosyaya belirli aralıklarla durumunu kaydeder. Oyunum sırasıyla kullanıcı veya işletim sistemi tarafından öldürüldüğünde veya çöktüğünde, geçerli dosya durumunu bu dosyaya yazıyoruz. Düzeltme aralığından sonra dosya yazma iyi çalışıyor ancak oyun OS veya kullanıcı tarafından çöktüğünde / öldürüldüğünde, dosya yazma işlemi başarısız oluyor. İşlem hatası eksik oyun durumu veya boş oyun durumu ile sonuçlanır, yani dosyaya hiç veri yazılmaz. Ben android hizmeti kullanarak birden çok çözüm denedim, servis OLMADAN STICKY hizmet uygulaması ile öldürülür. Öte yandan, hizmet STICKY ise, yeniden başlatılır ancak başlangıçta hizmete eklenen niyet null veya yenidir.

Soru şu ki, oyunum / uygulamam kullanıcı / işletim sistemi tarafından öldürüldüğünde verilerimi dahili depolama alanında tamamen (2-3MB olabilir) nasıl kaydedebilirim?


SIGTERM'lerinizi ve SIGKILL'lerinizi ele almalısınız (belki SIGKILL'ler değil, Android muhtemelen SIGTERM kullanıyor). (Tam bir cevap araştırmak / yazmak için zamanınız yok ama temel fikir bu.)
John Hamilton

2
@JohnHamilton SIGKILL tanım gereği ele alınamaz.
Darkhogg

@Darkhogg Peki, Unity'de değil, bu kesin. (Bu özel amaç için bir proje için linux çekirdeğini bir noktada değiştirdim ve programların SIGKILL'i kullanmasına izin vermek kesinlikle mümkün)
John Hamilton

Yanıtlar:


20

Geçmişte konsol başlıkları için yaygın olduğu gibi, kaydetme durumunuzu çift arabellekli bir şekilde yazmanızı öneririm (burada, orta kartın çıkarılmasının ve yazmaların yavaş kalmasıyla başa çıkmak zorunda kaldınız).

Kayıt etmek:

  • Hiçbir dosya yoksa, A dosyasına durum yazın
  • A varsa, B'ye yazın
  • A ve B'nin ikisi de varsa, hangisinin daha eski olduğunu bulun, silin ve sonra ona yazın

Yük:

  • Hem A hem de B varsa, ikisinden daha yenisini yüklemeyi deneyin. Bu başarısız olursa (dosya eksik veya bozuk olduğu için) dosyayı silin ve diğerini yükleyin
  • Yalnızca bir tane varsa yükleyin
  • Her ikisi de bozuksa, kullanıcıyı kaydetme durumunun geri alınamaz olduğu konusunda bilgilendirin (muhtemelen tahmin ettiğiniz gibi)

Bu akış, uygulama yazma ortasında öldürülse bile, depolama alanınızda her zaman en az bir geçerli kayıt bulunduğundan emin olmak için çalışır. Oyuncu, bu tür bir arıza meydana gelirse bir önceki kaydetmeden bu yana oyun durumundaki değişikliklerden hiçbirini alamaz, ancak tekrar başlaması gerekmez.

Ayrıca, bir kilitlenme / öldürmenin söz konusu önemli olayın kaybolmasına neden olacağı güvenlik açığı penceresini en aza indirmek için, aralıklı kaydetmenize ek olarak önemli olaylardan (uygulama içi satın alma gibi) hemen sonra tasarruf etmelisiniz. Bu aynı zamanda oyun istismarlarına karşı bir korumadır (örneğin, bir hayatını kaybettikten sonra uygulamayı zorla öldürmek, çünkü bir hayatınızı kaybetmeden önce bir oyun durumuna geri döneceğinizi ve tekrar denediğinizi biliyorsunuz). Tabii eğer bunu yaparsanız, "bir kaydetme işlemi devam ediyorsa, kaydetmeye yeniden başlamaya çalışmayın" yazan bir mantıkla aralık tasarrufunuzu korumalısınız.


Teşekkürler MrCranky bu benim sorunum kısmi bir çözüm nasıl uygulama / oyun öldürmeden önce yani son oturumun veri kaydedebilirsiniz? Örneğin bir uygulama satın alma ve öldürme uygulaması yaptı.
Faysal İmran

12
İki dosyaya bile ihtiyacınız yok. B'ye yazın, yalnızca yazma başarılı olursa, A'yı silin ve B'yi A java.nio.file.Files.move(Path source, Path target, CopyOption... options)olarak yeniden adlandırın, atomik bir işlem olarak yeniden adlandırma ve üzerine yazma yapabilir.
Polygnome

6
@Polygnome: Elektrik kesintileri durumunda, sync()A dosyası üzerinde taşımadan önce B dosyasını çağırmazsanız (bu durumda bile tam garanti yoktur, ancak sync()oldukça iyidir) , her zaman beklediğiniz garantileri sağlamayacağını unutmayın .
Dietrich Epp

1
@FaisalImran Önemli işlemden hemen sonra, örneğin IAP'den sonra verileri kaydedin. Operasyon telefonun kapatılmasıyla kesilirse, sanırım yine de kişiden asla para almayacaktır. Ancak, her ihtimale karşı, bir şey satın alma girişimi olarak hesap verilerini bazı platformlardaki bir satın alma işleminde kaydetmek isteyebilirsiniz. Daha sonra kazançlarınızı bu verilerle karşılaştırabilir ve bu kişinin gerçekten bir şey satın alıp almadığını görebilirsiniz. Ardından, tüm verileri kaydetmek için kullandığınız çevrimiçi hizmet aracılığıyla bu özelliği açın. IAP için yerel tasarruflar kullanıyorsanız, bu sorundan daha da kötüdür.
Candid Moon _Max_

1
Son olarak, bu tüm sorunlarınızı çözmese de, sorunun tamamen çözülemediğini söyleyebilirim. Hem "kullanıcı her zaman uygulamamı öldürebilir" hem de "hiçbir zaman hiçbir veri kaybı olmamalıdır" ı destekleyemezsiniz çünkü bir etkinlik gerçekleştikten sonra ancak kullanıcının depolandığı yerden devam etmeden önce her zaman bir pencere olacaktır Uygulamayı öldürebilir ve veri kaybedebilir.
MrCranky

3

Android, uygulamaları yalnızca arka planda olduklarında öldürür. Uygulama arka planda olduğunda oyun verilerinizin gerçekten güncellenmesi gerekiyor mu yoksa uygulama ön plana dönene kadar verileri güncellemeyi bırakabilir misiniz? Etkinliklerin geçmişini, hatta uygulama ön plana döndüğünde geçerli durumu bile alabiliyorsanız, çok oyunculu bir oyunda bile güncellemeleri erteleyebilirsiniz. Bu, CPU, ağ ve pil verimliliği uğruna muhtemelen bakmanız gereken bir şeydir.

Kullanıcı uygulamanızı öldürürse, çalışan hizmetlerin çağrılması gerekir onTaskRemoved. Bu yöntemde çok fazla işlem yapmaya çalışırsanız ne olacağını bilmiyorum. Belli bir süre içinde geri dönmezse Android'in kill -9uygulamanızı alacağını umuyorum.


uygulamanın arka planda güncellenmesi gerekmez, ancak uygulama arka plana veya imha etmeden önce verilerini yani json dosyasını kaydetmelidir.
Faysal İmran

haklısınızTaskRemoved yöntemi arayacak ancak dosyayı kaydetmek için gereken süre daha fazla veya hesaplama süresinin büyük olduğunu söyleyebiliriz. Kullanıcı uygulamayı öldürdüğünde bu yöntem durdurulacaktır.
Faisal Imran
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.