Приложение перезапускается из-за неправильной активностиAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Приложение перезапускается из-за неправильной активности

Сообщение Anonymous »

Это настоящая загадка:

Я открываю свое приложение. Он запускает действие, которое действует как заставка (ASplashscreen), в котором я загружаю некоторые данные JSON из локального хранилища (raw) и сохраните его в памяти в одноэлементном объекте (статическом). После завершения этого процесса он автоматически переходит к основному действию (AMain)

Я выхожу из приложения, нажимая кнопку «Домой», и запускаю другие приложения, игры и т. д. Когда я снова открываю свое приложение, приложение происходит сбой внутри метода onCreate AMain, поскольку он пытается использовать некоторые данные внутри одноэлементного объекта, но данные имеют значение NULL. Поэтому при этом он выдает исключение NullPointerException.
Похоже, что он перезапускает AMain вместо ASplashscreen, поэтому у синглтона нет возможности повторно инициализировать.

Это происходит случайным образом при нескольких таких попытках...

У меня есть два предположения...< /p>
  • Мое первое предположение, исходя из того, что я знаю об ОС Android, заключается в том, что пока я запускал другие приложения (особенно games) одному из них требовалось много памяти, поэтому ОС освободила мое приложение из памяти, чтобы освободить место, поэтому одноэлементные данные были собраны мусором.
  • Я также предполагаю, что хотя gc удалил мой синглтон из памяти, ОС все еще хранила некоторые данные, относящиеся к «состоянию» текущего запущенное действие, поэтому он знал, по крайней мере, что у него было открыто действие AMain, прежде чем я закрыл приложение. Это объясняет, почему он повторно открыл действие AMain вместо ASplashscreen.
Я Я прав? Или есть другое объяснение, почему я получаю это исключение? Любые предложения/уточнения приветствуются.

Кроме того, какой подход лучше всего подойдет для решения этой проблемы? Мой подход состоит в том, чтобы проверять наличие одноэлементных данных всякий раз, когда я пытаюсь их использовать, и если они равны нулю, то просто перезапускаю приложение. Это заставляет его проходить через ASplashscreen, поэтому JSON инициализируется, и все в порядке.

РЕДАКТИРОВАТЬ В соответствии с просьбой , вот мой AndroidManifest




















































Если вам это действительно нужно, вот содержимое ASplashscreen

/**
* @author MAB
*/
public class ASplashscreen extends ABase implements IIosLikeDialogListener {

private final float SHEEP_WIDTH_FRAC = 0.8f;

private final int SPLASHSCREEN_DELAY_MS = 500;

//View references
private View sheep_image;

/** The timestamp recorded when this screen came into view. We'll used this to determine how much we'll need to keep the splash screen awake */
private long mStartTimestamp;

private IosLikeDialog mDialog;

private IabHelper mIabHelper;

// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {

// Have we been disposed of in the meantime? If so, quit.
if (mIabHelper == null) {
System.out.println("=== IAB INVENTORY PROBLEM :: WE'VE BEEN DISPOSED");
displayAppStoreUnavailableDialog();
return;
}

// Is it a failure?
if (result.isFailure()) {
displayAppStoreUnavailableDialog();
System.out.println("=== IAB INVENTORY PROBLEM :: FAILED TO QUERY INVENTORY :: " + result);
return;
}

//Sync our static stuff with the app store
HSounds.instance().populate(ASplashscreen.this, inventory);
HLights.instance().populate(ASplashscreen.this, inventory);

//Store the stuff locally just to be sure
HStorage.persistObjectToFile(ASplashscreen.this, HVersions.SOUNDS);
HStorage.persistObjectToFile(ASplashscreen.this, HVersions.LIGHTS);

System.out.println("=== SUCCESSFULLY SYNCED WITH STORE !");

jumpToMainActivity();

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.a_splashscreen);

init();

}

@Override
protected void onDestroy() {
super.onDestroy();

if (mIabHelper != null) {
mIabHelper.dispose();
}
mIabHelper = null;
}

@Override
public void onIosLikeDialogBtnsClick(int btnStringResID) {
if (btnStringResID == IosLikeDialog.BTN_OK) {
jumpToMainActivity();
}
}

private void init() {
//Get view references
sheep_image = findViewById(R.id.splashscreen_sheep);

mStartTimestamp = System.currentTimeMillis();

VersionTracking.setVersions(this);

//Set the width of the sheep
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) sheep_image.getLayoutParams();
params.width = (int) ((float) UScreen.getScreenWidthInPortrait(this) * SHEEP_WIDTH_FRAC);
sheep_image.setLayoutParams(params);

mDialog = new IosLikeDialog()
.with(findViewById(R.id.ios_like_dialog_main_container))
.listen(this);

new Thread(new Runnable() {
@Override
public void run() {

parseJsons();

//Get the filler bar values from shared prefs
HBrightness.instance().retrieveFromPersist(ASplashscreen.this);
HSensorAndTimer.instance().retrieveFromPersist(ASplashscreen.this);

WsBuilder.build(ASplashscreen.this).getGift(new ResponseListener() {
@Override
public void onSuccess(EGift gifts) {
long now = System.currentTimeMillis();
SimpleDateFormat fmt = new SimpleDateFormat(HJsonDataBase.GIFT_DATE_FORMAT);
Date start;
Date end;

//Handle the gifts
if (gifts != null && gifts.data != null && gifts.responseOK()) {
//Go through the SOUNDS and check if we need to set them as gifts, if not reset them
for (ESound sound : HSounds.instance().getValues().getSounds()) {
String sku = sound.getSku(ASplashscreen.this);
sound.giftStart = null;
sound.giftEnd = null;
for (String giftSku : gifts.data.inapps) {
if (giftSku.equals(sku)) {
sound.giftStart = gifts.data.start_date;
sound.giftEnd = gifts.data.end_date;
break;
}
}
//Check if redeemed gift expired and if so, reset the dates
checkSoundGiftExpired(sound, fmt, now);
}
//Go through the LIGHTS and check if we need to set them as gifts, if not reset them
for (ELight light : HLights.instance().getValues().getLights()) {
String sku = light.getSku(ASplashscreen.this);
light.giftStart = null;
light.giftEnd = null;
for (String giftSku : gifts.data.inapps) {
if (giftSku.equals(sku)) {
light.giftStart = gifts.data.start_date;
light.giftEnd = gifts.data.end_date;
break;
}
}
//Check if redeemed gift expired and if so, reset the dates
checkLightGiftExpired(light, fmt, now);
}
//Persist the data in the local storage
HStorage.persistObjectToFile(ASplashscreen.this, HVersions.SOUNDS);
HStorage.persistObjectToFile(ASplashscreen.this, HVersions.LIGHTS);
}

//Run the IAB helper now
runIabHelper();
}

@Override
public void onErrorResponse(VolleyError error) {
//This might mean we're in offline mode, so check if the gifts expired
checkAllLightsGiftExpired();
checkAllSoundsGiftExpired();

//Run the IAB helper now
runIabHelper();
}
}, getPackageName());
}
});
}

/**
* This is run on a non-UI thread !!
*/
private void parseJsons() {

/**
* Versions
*/
parseVersions();

/**
* BACKGROUND
*/
parseBackgrounds();
try {
validateBackgrounds();
} catch (NullPointerException e) {
removeBackgroundsFile();
parseBackgrounds();
}

/**
* LIGHTS
*/
parseLights();
try {
validateLights();
} catch (NullPointerException e) {
removeLightsFile();
parseLights();
}

/**
* SOUNDS
*/
parseSounds();
try {
validateSounds();
} catch (NullPointerException e) {
removeSoundsFile();
parseSounds();
}

}

private void parseVersions() {
InputStream in = getResources().openRawResource(R.raw.versions);
EVersions versions = null;
try {
versions = UGson.jsonToObject(in, EVersions.class);
} catch (Exception e) {
System.out.println("==== PARSE ERROR :: VERSIONS :: " + e.getMessage());
e.printStackTrace();
return;
}
HVersions.instance().setValues(this, versions);
}

private void parseBackgrounds() {
//Get the version of he JSONS at which we've last updated them from the "raw" folder
int lastVersionBckgnds = UPersistent.getInt(ASplashscreen.this, HVersions.SHARED_PREF_LAST_JSONS_VERSION_BCKGNDS, 0);

InputStream in;
//If there are no files in local storage OR there's a new version of the JSON files that we need to retrieve
if (!HStorage.fileExists(ASplashscreen.this, HStorage.FILE_JSON_BACKGROUNDS) ||
HVersions.instance().shouldUpdateFromResources(HVersions.BACKGROUNDS, lastVersionBckgnds)) { //Update from raw folder
in = getResources().openRawResource(R.raw.backgrounds);
} else { //Update from local storage
in = HStorage.getInputStreamForFile(ASplashscreen.this, HStorage.FILE_JSON_BACKGROUNDS);
}
EBackgrounds bckgnds = null;
try {
bckgnds = UGson.jsonToObject(in, EBackgrounds.class);
} catch (Exception e) {
System.out.println("==== PARSE ERROR :: BACKGROUNDS :: " + e.getMessage());
e.printStackTrace();
}
HBackgrounds.instance().setValues(this, bckgnds);
}

private void parseLights() {
//Get the version of he JSONS at which we've last updated them from the "raw" folder
int lastVersionLights = UPersistent.getInt(ASplashscreen.this, HVersions.SHARED_PREF_LAST_JSONS_VERSION_LIGHTS, 0);

InputStream in;
//If there are no files in local storage OR there's a new version of the JSON files that we need to retrieve
if (!HStorage.fileExists(ASplashscreen.this, HStorage.FILE_JSON_LIGHTS) ||
HVersions.instance().shouldUpdateFromResources(HVersions.LIGHTS, lastVersionLights)) { //Update from raw folder
in = getResources().openRawResource(R.raw.lights);
} else { //Update from local storage
in = HStorage.getInputStreamForFile(ASplashscreen.this, HStorage.FILE_JSON_LIGHTS);
}
ELights lights = null;
try {
lights = UGson.jsonToObject(in, ELights.class);
} catch (Exception e) {
System.out.println("==== PARSE ERROR :: LIGHTS :: " + e.getMessage());
e.printStackTrace();
}
if (lights != null) {
HLights.instance().setValues(this, lights);
}
}

private void parseSounds() {
int lastVersionSounds = UPersistent.getInt(ASplashscreen.this, HVersions.SHARED_PREF_LAST_JSONS_VERSION_SOUNDS, 0);

InputStream in;
//If there are no files in local storage OR there's a new version of the JSON files that we need to retrieve
if (!HStorage.fileExists(ASplashscreen.this, HStorage.FILE_JSON_SOUNDS) ||
HVersions.instance().shouldUpdateFromResources(HVersions.SOUNDS, lastVersionSounds)) { //Update from raw folder
in = getResources().openRawResource(R.raw.sounds);
} else { //Update from local storage
in = HStorage.getInputStreamForFile(ASplashscreen.this, HStorage.FILE_JSON_SOUNDS);
}
ESounds sounds = null;
try {
sounds = UGson.jsonToObject(in, ESounds.class);
} catch (Exception e) {
System.out.println("==== PARSE ERROR :: SOUNDS" + e.getMessage());
}
if (sounds != null) {
HSounds.instance().setValues(this, sounds);
}
}

private void validateBackgrounds() throws NullPointerException {
if (HBackgrounds.instance().getValues() == null) {
throw new NullPointerException();
}
if (HBackgrounds.instance().getValues().getBackgrounds() == null) {
throw new NullPointerException();
}
}

private void validateLights() throws NullPointerException {
if (HLights.instance().getValues() == null) {
throw new NullPointerException();
}
if (HLights.instance().getValues().getLights() == null) {
throw new NullPointerException();
}
}

private void validateSounds() throws NullPointerException {
if (HSounds.instance().getValues() == null) {
throw new NullPointerException();
}
if (HSounds.instance().getValues().getSounds() == null) {
throw new NullPointerException();
}
}

private void removeBackgroundsFile() {
HStorage.deleteFile(this, HStorage.FILE_JSON_BACKGROUNDS);
}

private void removeLightsFile() {
HStorage.deleteFile(this, HStorage.FILE_JSON_LIGHTS);
}

private void removeSoundsFile() {
HStorage.deleteFile(this, HStorage.FILE_JSON_SOUNDS);
}

private void runIabHelper() {

//If there's no network connection, then ... sorry
if (!UNetwork.isNetworkAvailable(this)) {
displayAppStoreUnavailableDialog();
System.out.println("=== IAB ERROR :: NO NETWORK");
return;
}

try {
mIabHelper = new IabHelper(ASplashscreen.this, CIab.IAB_PUBLIC_KEY);
mIabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
System.out.println("=== IAB ERROR :: CONNECTION :: " + result);
displayAppStoreUnavailableDialog();
return;
}

//Obtain and create the list of skus from both the LIGHTS and the SOUNDS handlers
List skus = new ArrayList();
skus.addAll(HSounds.instance().createSkuList(ASplashscreen.this, true));
skus.addAll(HLights.instance().createSkuList(ASplashscreen.this, true));

//Get the inventory
try {
mIabHelper.queryInventoryAsync(true, skus, mGotInventoryListener, new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// Crashlytics.logException(ex);
System.out.println("=== IAB ERROR :: query inventory crashed :: " + ex.getMessage());
displayAppStoreUnavailableDialog();
}
});
} catch (IllegalStateException e) {
displayAppStoreUnavailableDialog();
}
}
});
} catch (NullPointerException e1) {
// Crashlytics.logException(e1);
System.out.println("=== IAB ERROR :: query inventory crashed :: " + e1.getMessage());
displayAppStoreUnavailableDialog();
} catch (IllegalArgumentException e2) {
// Crashlytics.logException(e2);
System.out.println("=== IAB ERROR :: query inventory crashed :: " + e2.getMessage());
displayAppStoreUnavailableDialog();
}
}

private void displayAppStoreUnavailableDialog() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mDialog == null) {
return;
}
mDialog.reset()
.header(R.string.inapp_store_unavailable_header)
.subheader(R.string.inapp_store_unavailable_subheader)
.btnOK()
.show();
}
});
}

private void jumpToMainActivity() {

int timePassed = (int) (System.currentTimeMillis() - mStartTimestamp);

int delay = (timePassed > SPLASHSCREEN_DELAY_MS) ? 0 : (SPLASHSCREEN_DELAY_MS - timePassed);

new Handler().postDelayed(new Runnable() {
@Override
public void run() {

//In case we need to display the tutorial, then do so
if (AHelp.shouldDisplayTutorial(ASplashscreen.this)) {
CrashReport.log("ASplashscreen -> AHelp");
Intent i = new Intent(ASplashscreen.this, AHelp.class);
i.putExtra(AHelp.BUNDLE_SHOW_TUTORIAL, true);
startActivity(i);
finish();
overridePendingTransition(R.anim.anim_slide_in_from_bottom, R.anim.anim_stay_put);
return;
} else { //Otherwise continue with normal flow
CrashReport.log("ASplashscreen -> AMain");
Intent i = new Intent(ASplashscreen.this, AMain.class);
i.putExtra(AMain.BUNDLE_DEBUGGING_CAME_FROM_SPLASHSCREEN, true);
startActivity(i);
finish();
}

}
}, delay);
}

private void checkAllSoundsGiftExpired() {
SimpleDateFormat fmt = new SimpleDateFormat(HJsonDataBase.GIFT_DATE_FORMAT);
long now = System.currentTimeMillis();

for (ESound sound : HSounds.instance().getValues().getSounds()) {
if (sound != null) {
checkSoundGiftExpired(sound, fmt, now);
}
}
}

private void checkAllLightsGiftExpired() {
SimpleDateFormat fmt = new SimpleDateFormat(HJsonDataBase.GIFT_DATE_FORMAT);
long now = System.currentTimeMillis();

for (ELight light : HLights.instance().getValues().getLights()) {
if (light != null) {
checkLightGiftExpired(light, fmt, now);
}
}
}

private void checkSoundGiftExpired(ESound sound, SimpleDateFormat fmt, long now) {
if (UString.stringsExist(sound.giftExpireStart, sound.giftExpireEnd)) {
try {
Date start = fmt.parse(sound.giftExpireStart);
Date end = fmt.parse(sound.giftExpireEnd);
if (now < start.getTime() || end.getTime() < now) {
sound.giftExpireStart = null;
sound.giftExpireEnd = null;
}
} catch (ParseException e) {
//Do nothin'
}
}
}

private void checkLightGiftExpired
(ELight light, SimpleDateFormat fmt, long now) {
if (UString.stringsExist(light.giftExpireStart, light.giftExpireEnd)) {
try {
Date start = fmt.parse(light.giftExpireStart);
Date end = fmt.parse(light.giftExpireEnd);
if (now < start.getTime() || end.getTime() < now) {
light.giftExpireStart = null;
light.giftExpireEnd = null;
}
} catch (ParseException e) {
//Do nothin'
}
}
}

}


Подробнее здесь: https://stackoverflow.com/questions/294 ... g-activity
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»