Как приложения сохраняют данные

Это может быть глупый вопрос, а также может быть дубликат. Но я действительно не знаю и вообще не мог найти решение. У меня вопрос, как приложения сохраняют данные. Я делаю приложение с LibGDX и Java для устройств Android, и я просто зациклился на этом. Почему, например, когда я закрываю Candy Crush и снова открываю его на следующий день, он запоминает, где я нахожусь, даже если приложение перезагружается? Если это действительно дубликат, я был бы очень признателен другому форуму и извиняюсь за дублирование. Я просто не смог его найти. Заранее спасибо!


person Shivashriganesh Mahato    schedule 17.09.2015    source источник
comment
Существуют десятки способов сделать это ... от Candy Crush ... это простые веб-службы, которые запоминают состояние, передавая данные с сервера в приложение. Другими способами являются использование SharedPreference или использование папки каталога для сохранения данных на SD-карте. Другой вариант - SQL. Дело в том ... что нет уникального способа, лучший способ сохранить данные - тот, который работает для вас.   -  person Mariano Zorrilla    schedule 17.09.2015
comment
Вы когда-нибудь играли в игры на своем компьютере? Как получается, что игра запоминает, на каком вы уровне и какой у вас счет. Почему Android Java или Native Java должны отличаться и не иметь возможности хранить данные удаленно или на устройстве и извлекать их при запуске приложения. Это не волшебство, это просто язык программирования, такой же, как и любой другой.   -  person Tasos    schedule 17.09.2015


Ответы (4)


Это широкий вопрос, но я стараюсь охватить некоторые элементы взгляда на эту тему. Candy Crush Sage сбрасывается, если вы не зарегистрируете или не свяжете свою учетную запись с чем-то вроде Facebook и переустановите приложение. Скорее всего, они используют базу данных для хранения вещей. Если вы не зарегистрированы, вещи могут просто храниться локально.

LibGDX предлагает удобную функцию для локального хранения данных. Он называется «Настройки», и вы просто пишете в него, и в следующий раз, когда вы открываете приложение, оно сохраняется.

Preferences pref = Gdx.app.getPreferences("somefile");
pref.putString("name", "Menyo");
pref.putInteger("level", 20);

Однако, когда вы удаляете, эти данные идут вместе с ним, и они не очень безопасны для игроков, которые любят «исследовать». Другое дело, что вы можете хранить свои собственные созданные данные в каком-то месте. Если вы храните его вне внутреннего приложения, он сохраняется даже после удаления приложения, и пока данные остаются, а ваше приложение выглядит в том же месте после переустановки, вы сможете получить данные. Но, как и следовало ожидать, это тоже не безотказно.

Единственный реальный способ убедиться - это иметь какой-то механизм входа в систему. Самый жизнеспособный способ - это база данных. У меня сейчас работает аналогичная система, но между клиентом и базой данных есть сервер. Вы можете хранить любые данные в базе и привязать их к игроку по его ID.

  • Новые игроки могут выбрать игру в качестве гостя. Будет создана новая учетная запись с именем "Guest" + id. Когда игрок связывает свою учетную запись с чем-то вроде Facebook или адресом электронной почты, учетная запись сохраняется, как и связанные с ней данные.

  • Существующие проигрыватели войдут в систему при установке вашего приложения, и вы можете сохранить данные для входа на свое устройство, чтобы они автоматически выполняли вход, если эти данные существуют и действительны.

При настройке базы данных я настоятельно рекомендую никогда не подключаться к базе данных напрямую через клиентское устройство. Либо у меня есть веб-сервис, либо как будто я сейчас делаю KryoNet сервер. Причина в том, что вам нужно очистить данные, поступающие от клиентов. Вы можете сделать это с клиентского устройства, но у вас нет полного контроля над ним. Всегда выполняйте дезинфекцию пользовательского ввода на стороне сервера.

Создать веб-сервис для подключения через базу данных довольно просто, если вы немного знакомы с PHP и mysql. Все, что вам нужно, - это отправить HttpRequest на эту страницу php и позволить ему сделать свою работу.

public class WebTest {
    HttpRequestBuilder builder;
    Net.HttpRequest request;

    public WebTest()
    {
        builder = new HttpRequestBuilder();
        request = builder.newRequest().method(Net.HttpMethods.GET).url("http://yourdomain.com/script.php").build();
        request.setHeader("Content-Type", "application/x-www-form-urlencoded");


        final long start = System.nanoTime();
        Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
            @Override
            public void handleHttpResponse(Net.HttpResponse httpResponse) {
                Gdx.app.log("Test", "HTTP Response code: " + httpResponse.getStatus().getStatusCode());
                Gdx.app.log("Test", "HTTP Response code: " + httpResponse.getResultAsString());
                Gdx.app.log("Test", "Response time: " + ((System.nanoTime() - start) / 1000000) + "ms");
            }

            @Override
            public void failed(Throwable t) {
                Gdx.app.log("Test", "HTTP request failed");
            }

            @Override
            public void cancelled() {
                Gdx.app.log("Test", "HTTP request cancelled");
            }
        });
    }
}

Поместите php-скрипт с именем script.php в yourdomain.com и выведите что-нибудь в нем. Затем этот код должен получить это эхо внутри вашего приложения.

Вы также можете создать xml и проанализировать его с помощью вашего любимого парсера. Но вы должны установить заголовок запроса, чтобы правильно получать xml.

request.setHeader("Content-Type", "text/xml");

Вот соединение PHP MySQL, которое отправляет обратную связь в XML.

<?php
$link = mysqli_connect("127.0.0.1", "root", "", "chatapp");
$xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><mysql></mysql>");
if (!$link)
{
    $xml->addChild("error", "Error: Unable to connect to MySQL.");
    $xml->addChild("error", "Debugging errno: " . mysqli_connect_errno());
    $xml->addChild("error", "Debugging error: " . mysqli_connect_error());
    exit;
}

$xml->addChild("success", "Success: A proper connection to MySQL was made!");
$xml->addChild("success", "Host information: " . mysqli_get_host_info($link));

//Sends the xml to whoever requested this
print($xml->asXML());

mysqli_close($link);
?>

Теперь вы можете просто использовать PHP для входа пользователя в базу данных, как если бы вы делали это с обычной веб-страницей. Есть много руководств по php, посвященных этой теме. Конечно, для этого можно использовать любой скрипт на стороне сервера.

Ваш собственный сервер для подключения к базе данных тоже возможен, но требует гораздо больше работы. Но KryoNet требует от вас много работы. Наличие собственного сервера означает, что вы можете хранить данные на сервере и очень быстро обмениваться ими через TCP или UDP-соединение. По сути, у вас гораздо больше контроля над тем, что обменивается.

person Madmenyo    schedule 17.09.2015
comment
Лично я использую Realm на стороне Android. Это ORM, который делает жизнь очень простой. realm.io вы также можете использовать сериализацию Java для хранения и шифрования объектов. Я просто хотел предложить несколько альтернативных предложений. Хотя сериализация не рекомендуется чрезмерно, она интересна как выбор. developer.android.com/reference/java/io/Serializable.html - person Jesson Atherton; 17.09.2015

Многие игры используют разные подходы к этому в зависимости от своих требований. В таких играх, как Candy Crush, Age of War или Clash of Clans, вся пользовательская информация хранится в онлайн-базе данных. Информация о пользователе извлекается при запуске из указанной базы данных. Затем вы можете сохранить эту информацию локально, чтобы она загружалась быстрее. Затем в следующий раз, когда вы запустите приложение, вы загрузите данные локально, а если не можете, снова загрузите их с сервера. Вы можете отправлять новую информацию на сервер каждый раз, когда хотите сохранить состояние игры. Трудно дать вам конкретный ответ, не зная, какую игру вы делаете.

Вам следует прочитать этот пост: Какой метод хранения данных Android использовать? В нем много информации по сохранению данных на android.

Синхронизация данных между приложением Android и веб-сервером Еще один хороший пост для чтения через. Он дает вам некоторую информацию о том, как синхронизировать данные, которые вы сохранили локально и на веб-сервере.

Облачное хранилище Google также является еще одним вариантом: https://cloud.google.com/solutions/mobile/how-to-build-mobile-app-with-app-engine-backend-tutorial/

Google также предлагает службу сохраненных игр: https://developers.google.com/games/services/common/concepts/savedgames?hl=en

Если, однако, вы просто делаете простую игру. Я рекомендую вам использовать локальную базу данных в сочетании с общими настройками.

Если вы храните данные только локально, есть вероятность «взлома». Если у вас есть данные на сервере и локально, вы можете «рукопожатие» и проверить правильность данных.

person Community    schedule 17.09.2015

Есть много способов сделать это.

Для некоторых онлайн-приложений они использовали сетевое соединение для связи со своими серверами, такими как онлайн-серверы MYSQL, веб-службы и т. Д.

Для автономного приложения используются SQLite, SharedPreferences, внутреннее и внешнее хранилище.

http://developer.android.com/guide/topics/data/data-storage.html

person cw fei    schedule 17.09.2015

Это зависит от того, что вы хотите спасти. Есть много способов сохранить вещи, о которых упоминали другие. Если вы хотите сохранить на устройстве только одну переменную, вам, вероятно, будет лучше всего использовать pref.


Вот как вы можете использовать pref.

//This is how you can store a boolean, using a pref
SharedPreferences prefs = getSharedPreferences("BOOL", MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putBoolean("ads", showAds);
        editor.commit();

`//showAds is a boolean that you are storing

вы можете создать функцию для извлечения сохраненного логического значения, подобного этому

public boolean checkStoredBool(){
        SharedPreferences prefs = getSharedPreferences("BOOL", MODE_PRIVATE);
        boolean extractedBool = prefs.getBoolean("ads", false);
        return extractedBool;
    }

//The false in the previous code, is what would be called in if no value was stored

Вы хотите убедиться, что при создании SharedPreferences часть в кавычках соответствует тому, что вы вводили в коды при сохранении логического значения.

Также при вызове prefs.getBoolean часть в кавычках должна соответствовать тому, что было в кавычках, когда вы использовали editor.putBoolean ранее.


Теперь в вашем коде, если вы хотите вызвать сохраненный код, вы просто вызываете метод.

Например, если вы хотите иметь оператор if, который проверяет, было ли сохраненное значение истинным или ложным, он будет выглядеть примерно так

if(checkStoredBool() == true){
    //code when it's true
}
else{
    //code when it's false
}
person Josiah Lauby    schedule 18.09.2015
comment
Я собираюсь сделать игру с разными уровнями и разблокированными элементами выбора уровня, достижениями, общим количеством очков и т. Д. Итак, серию переменных и массивов. - person Shivashriganesh Mahato; 19.09.2015
comment
Я добавил более подробную информацию о том, как вы можете использовать prefs. Позвольте мне знать, если это помогает. Я знаю, что уже немного поздно. Или очень поздно. - person Josiah Lauby; 13.02.2017