Obiekt -> Json -> Json -> Obiekt SharedPreferences

0

Cześć, piszę apkę i jedna z jej funkcji to pobranie informacji i zainstalowanych aplikacjach na telefonie.
Umieszczam sobie ją w liście (ArrayList) a siedzą w niej obiekty.

I chciał bym dać sobie możliwość zapisania tych obiektów, odczytania zawartości i ponowne ich wyświetlenie. Odczyt dokonanie zmiany, zapis i po ponownym uruchomieniu apki znowu najpierw odczyt.

Listę obiektów konwertuję do jsona, i to mi zapisuje. Ale przy uruchomieniu apki i startowym odczytaniu apka się wywala.

apps = loadData(); // TUTAJ SIE WYWALA, jednak chodzi o wnętrze funkcji

        if(apps == null)
        {
            Toast.makeText(this,"Empty",Toast.LENGTH_LONG).show();
            apps = new ArrayList<>();
        }
        else
        {
            Toast.makeText(this,"NIEEmpty",Toast.LENGTH_LONG).show();
            //listAppView.setAdapter(new AppAdapter(SetingsActivity.this,apps));
        }
 

teraz co się dzieje w loadData():

private ArrayList<AppInfo> loadData()
    {
        SharedPreferences sharedPreferences = getSharedPreferences(getString(R.string.sheredApps),MODE_PRIVATE);
        Gson gson = new Gson();
        String json = sharedPreferences.getString(getString(R.string.sheredAppsKeyList),"");
        Type type = new TypeToken<List<AppInfo>>() {}.getType();
        //Log.i("JSON: ",json);

        ArrayList<AppInfo> list = gson.fromJson(json, type);  // TUTAJ SIĘ WYWALA
        return list;
    }

Teraz co się znajduje w AppInfo. Bo w obiekcie AppInfo mam też inny obiekt ApplicationInfo, ta klasa jest tymczasowa. Będzie się rozrastać:

public class AppInfo {

    public ApplicationInfo info;
    public String label;

    public AppInfo(ApplicationInfo info, String label)
    {
        this.info = info;
        this.label = label;
    }
}

Funkcja zapisująca zapisuje tak:

 private void saveData()
    {
        SharedPreferences sharedPreferences = getSharedPreferences(getString(R.string.sheredApps),MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        Gson gson = new Gson();
        String json = gson.toJson(apps);
        editor.putString(getString(R.string.sheredAppsKeyList),json);
        editor.apply();
       // for (AppInfo ap: apps) { Log.i("Apka: ",""+ap.toString()); }
    }

I jej rezultat:

2/X.pl I/Apka:: X.pl.objects.AppInfo@c08e60e
2020-11-04 20:30:22.592 13252-13252/X.pl I/Apka:: X.pl.objects.AppInfo@2b6682f
2020-11-04 20:30:22.592 13252-13252/X.pl I/Apka:: X.pl.objects.AppInfo@ec2de3c
2020-11-04 20:30:22.592 13252-13252/X.pl I/Apka:: X.pl.objects.AppInfo@71717c5

Natomiast Json po próbie odczytania wygląda tak:

I/JSON:: [{"info":{"category":-1,"compatibleWidthLimitDp":0,"credentialProtectedDataDir":"/data/user/0/com.android.cts.priv.ctsshim","dataDir":"/data/user/0/com.android.cts.priv.ctsshim","descriptionRes":0,"deviceProtectedDataDir":"/data/user_de/0/com.android.cts.priv.ctsshim","enabled":true,"enabledSetting":0,"flags":-1198997951,"fullBackupContent":0,"installLocation":-1,"largestWidthLimitDp":0,"maxAspectRatio":0.0,"minSdkVersion":24,"nativeLibraryDir":"/system/priv-app/CtsSh
 

Natomiast mam wrażenie że on się ucina i też gdzieś ginie.

Ma ktoś jakieś pomysły/sugestie ?

0

Dobra, dokonałem modyfikacji.
Teraz program nie wysypuje się na zapisie/odczycie.
Tak wyglądają funkcje:

private void saveData()
    {
        SharedPreferences sharedPreferences = getSharedPreferences(getString(R.string.sheredApps),MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        GsonBuilder builder = new GsonBuilder();
        builder.excludeFieldsWithModifiers(Modifier.FINAL,Modifier.TRANSIENT,Modifier.STATIC);
        builder.excludeFieldsWithoutExposeAnnotation();
        Gson sExposeGson = builder.create();
        String jsonObject = sExposeGson.toJson(apps);
        editor.putString(getString(R.string.sheredAppsKeyList),jsonObject);
        editor.commit();


        for (AppInfo ap: apps) { Log.i("Apka: ",""+ap.toString()); }
    }

    private ArrayList<AppInfo> loadData()
    {
        SharedPreferences sharedPreferences = getSharedPreferences(getString(R.string.sheredApps),MODE_PRIVATE);

        if(sharedPreferences.contains(getString(R.string.sheredAppsKeyList))) {
            String jsonObject = sharedPreferences.getString(getString(R.string.sheredAppsKeyList), null);

            GsonBuilder builder = new GsonBuilder();
            builder.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC);
            builder.excludeFieldsWithoutExposeAnnotation();
            Gson sExposeGson = builder.create();
            AppInfo[] items = sExposeGson.fromJson(jsonObject, AppInfo[].class);
            apps = Arrays.asList(items);
            apps = new ArrayList(apps);
        }
        else
        {
            return null;
        }
        return (ArrayList) apps;
    }

Program wywala się gdy załaduje dane do listy

  apps = loadData();

        if(apps == null)
           apps = new ArrayList<>();
        
        else
            listAppView.setAdapter(new AppAdapter(SetingsActivity.this,apps)); // tutaj

Problem pojawił się w adapterze:

@NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        AppInfo current = apps.get(position);
        View view = convertView;

        if(view == null)
        {
            view = layoutInflater.inflate(R.layout.app_item_layout, parent,false);
        }

        mTitle = view.findViewById(R.id.appTitle);
        mVerion = view.findViewById(R.id.versionId);
        imageView = view.findViewById(R.id.iconImage);


        try
        {

            PackageInfo packageInfo = packageManager.getPackageInfo(current.info.packageName, 0);  // TUTAJ WYSYPUJE BŁĄD

            mTitle.setText(current.label);

            if(!TextUtils.isEmpty(packageInfo.versionName))
            {
                String verion = String.format("%s",packageInfo.versionName);
                mVerion.setText(verion);
            }

            Drawable icon = current.info.loadIcon(packageManager);
            imageView.setBackgroundDrawable(icon);
        }
        catch (PackageManager.NameNotFoundException e)
        {
            e.printStackTrace();
        }

        return view;
    }

Nie mam zielonego pojęcia o co chodzi :/
Gdy lista jest pusta i skanuję wszystko. Adapter normalnie działa. To po odczycie zapisanych nawala, więc dalej błąd z zapisem/odczytem

0

Twój prywatny projekt for fun czy praca? Napisz proszę szerszy kontekst dlaczego korzystasz z tego kodu.

0

Aplikacja ma przechwytywać powiadomienia pojawiające się na telefonie i prowadzić statystykę jakie to mają być powiadomienia, jaka apka ile itd.
W późniejszym etapie te powiadomienia mają być przesyłane na urządzenie zewnętrzne PC.

Po co mi ten scan telefonu i zapis.
Wymyśliłem to w ten sposób że apka będzie miała zapisane obiekty zeskanowanych apek. Zawsze zapisane gdzieś, dla jakich apek ma liczyć, a dla jakich nie.
Jeżeli będę to trzymał na liście, to po wyłączeniu apki mi to zniknie. Albo jak padnie zasilanie też.
Więc po operacji skanowania muszę zapisać ustawienia.

Po wyłączeniu aplikacji docelowo ma chodzić serwis który będzie nasłuchiwał powiadomień. I jeżeli jakieś wystąpi, a w pamięci nie będzie miał listy obiektów apek.
Odtworzy sb z sheredPreferneces zadaną listę z ustawieniami.

Tak to wymyśliłem.
Ma to w miarę sens ? Czy da się to jakoś usprawnić ?

0

Z tego co widzę, metoda zapisu też nie działa. File Explorer pokazuje puste obiekty:
screenshot-20201105184941.png

Trochę zmieniłem działanie, ale dalej nie ruszę.
Metoda zapisująca:

private void saveData()
    {
        SharedPreferences sharedPreferences = getSharedPreferences(getString(R.string.sheredApps),MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        GsonBuilder builder = new GsonBuilder();
        builder.excludeFieldsWithModifiers(Modifier.FINAL,Modifier.TRANSIENT,Modifier.STATIC);
        builder.excludeFieldsWithoutExposeAnnotation();
        Gson sExposeGson = builder.create();
        String jsonObject = sExposeGson.toJson(apps);
        editor.putString(getString(R.string.sheredAppsKeyList),jsonObject);
        editor.commit();
        
        for (AppInfo ap: apps) { Log.i("Apka: ",""+ap.toString()); }
    }

Nie zapisuje, puste obiekty są. Przerobiłem trochę klasę która ma trzymać te obiekty. Zapisuje do niej wszystkie dane.
Ale, to nie zmienia faktu, dlaczego obiekty są puste.

Jakieś inne pomysły na zapis ? Albo ktoś widzi błąd ?

for w logach wywala że lista jest pełna i zawiera obiekty:

screenshot-20201105185721.png

Natomiast próba odczytu wyrzuca coś takiego:

screenshot-20201105185801.png

I tylko tyle elementów

0

Problem jest z Gsonem, funkcje są poprawne, natomiast w klasie należy dać adnotacje @expose - dzięki temu zmienne prymitywne dają się zapisać.
Problem jest z obiektem typu Drawable, czyli ikonkom. Nie wiem jeszcze jak to zapisać, wywala się przez to program

0

Jak mam Drawable icon;
mogę zrobić:

String src = icon.toString();

wtedy mogę uzyskać coś takiego na przykład: "android.graphics.drawable.AdaptiveIconDrawable@d5de697"

Ktoś wie jak potem z tego stringa odzyskać znowu iconkę ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1