简体   繁体   中英

Using SharedPreferences in Android Things

I am attempting to use SharedPreferences in my Things application, but it always returns 0 for some reason. My setter is getting is logging tht it pushed the right data using the editor, but every read, even after restarting the activity, is always 0. I can't find a reason why Things wouldn't allow use of SharedPreferences, even with a needed permission change, so I'm kind of at a loss. It's obviously my code, but I can't figure out why.

My goal is to use a TextView which is touchable to simply update the date when touched. No buttons, no real interaction, and it's simple and clean. But if SharedPreferences doesn't work, this gets more difficult.

I have been all over different ways of instantiating the SharedPreferences object, in OnCreate, each time I use it to no effect. I have also used a global and local editor to the Activity, to no effect. Writes seem to succeed, but reads always return 0 for getLong(). I switch from apply() to commit() thinking maybe it's just a timing problem. However, exiting and starting the activity again doesn't show a value either, it's still 0.

What is included is the latest based on what I found in the Android documentation based on what I know about Java. The first is just what I believe to be relevant to the question. The second code sample is the full activity.

public class DataViewActivity extends Activity {
    private static final String TAG = DataViewActivity.class.getSimpleName();

    TextView m_textViewTemperature;
    TextView m_textViewWaterLevel;
    TextView m_textViewIronAddition;
    TextView m_textViewWaterChange;
    TextView m_textViewFilterChange;
    Handler m_exitHandler = new Handler();

    SharedPreferences m_preferences;

    public static final String PREFERENCES = "aquarium";
    public static final String WATER_CHANGE = "waterchange";
    public static final String FILTER_CHANGE = "filterchange";
    public static final String IRON_ADD = "ironaddition";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_data_view);

        m_preferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE);
        m_textViewTemperature = findViewById(R.id.textViewTemperatureData);
        m_textViewWaterLevel = findViewById(R.id.textViewWaterLevelData);
        m_textViewFilterChange = findViewById(R.id.textViewFilterChangeDateData);
        m_textViewIronAddition = findViewById(R.id.textViewIronAdditionDateData);
        m_textViewWaterChange = findViewById(R.id.textViewWaterChangeDateData);

        m_textViewWaterChange.setOnTouchListener(new View.OnTouchListener() {
            @SuppressLint("ClickableViewAccessibility")
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    Long time = Calendar.getInstance().getTimeInMillis();
                    SharedPreferences.Editor e = m_preferences.edit();
                    e.putLong(WATER_CHANGE, time);
                    e.commit();
                    Log.i(TAG, "Stored " + time + " to shared preferences for last water change");
                    updateWaterChangeDate();
                }

                return false;
            }
        });
    }

    private void updateWaterChangeDate()
    {
        Calendar c = Calendar.getInstance();
        Long item = m_preferences.getLong("WaterChange", 0);
        Log.d(TAG, "Got " + item + " for last water change millis");
        c.setTimeInMillis(item);
        SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d");
        m_textViewWaterChange.setText(df.format(c.getTime()));
    }

package com.home.pete.aquarium;

import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import java.util.prefs.Preferences;

import static com.home.pete.aquarium.Constants.VIEW_TIMEOUT;
import static java.lang.Long.getLong;

/**
 * Skeleton of an Android Things activity.
 * <p>
 * Android Things peripheral APIs are accessible through the class
 * PeripheralManagerService. For example, the snippet below will open a GPIO pin and
 * set it to HIGH:
 *
 * <pre>{@code
 * PeripheralManagerService service = new PeripheralManagerService();
 * mLedGpio = service.openGpio("BCM6");
 * mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
 * mLedGpio.setValue(true);
 * }</pre>
 * <p>
 * For more complex peripherals, look for an existing user-space driver, or implement one if none
 * is available.
 *
 * @see <a href="https://github.com/androidthings/contrib-drivers#readme">https://github.com/androidthings/contrib-drivers#readme</a>
 */
public class DataViewActivity extends Activity {
    private static final String TAG = DataViewActivity.class.getSimpleName();

    TextView m_textViewTemperature;
    TextView m_textViewWaterLevel;
    TextView m_textViewIronAddition;
    TextView m_textViewWaterChange;
    TextView m_textViewFilterChange;
    Handler m_exitHandler = new Handler();

    SharedPreferences m_preferences;

    public static final String PREFERENCES = "aquarium";
    public static final String WATER_CHANGE = "waterchange";
    public static final String FILTER_CHANGE = "filterchange";
    public static final String IRON_ADD = "ironaddition";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_data_view);

        m_preferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE);
        m_textViewTemperature = findViewById(R.id.textViewTemperatureData);
        m_textViewWaterLevel = findViewById(R.id.textViewWaterLevelData);
        m_textViewFilterChange = findViewById(R.id.textViewFilterChangeDateData);
        m_textViewIronAddition = findViewById(R.id.textViewIronAdditionDateData);
        m_textViewWaterChange = findViewById(R.id.textViewWaterChangeDateData);

        m_textViewWaterChange.setOnTouchListener(new View.OnTouchListener() {
            @SuppressLint("ClickableViewAccessibility")
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    Long time = Calendar.getInstance().getTimeInMillis();
                    SharedPreferences.Editor e = m_preferences.edit();
                    e.putLong(WATER_CHANGE, time);
                    e.commit();
                    Log.i(TAG, "Stored " + time + " to shared preferences for last water change");
                    updateWaterChangeDate();
                }

                return false;
            }
        });

        m_textViewIronAddition.setOnTouchListener(new View.OnTouchListener() {
            @SuppressLint("ClickableViewAccessibility")
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    Long time = Calendar.getInstance().getTimeInMillis();
                    SharedPreferences.Editor e = m_preferences.edit();
                    e.putLong(IRON_ADD, time);
                    e.commit();
                    Log.i(TAG, "Stored " + time + " to shared preferences for last iron addition");
                    updateIronAdditionDate();
                }

                return false;
            }
        });

        m_textViewFilterChange.setOnTouchListener(new View.OnTouchListener() {
            @SuppressLint("ClickableViewAccessibility")
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    Long time = Calendar.getInstance().getTimeInMillis();
                    SharedPreferences.Editor e = m_preferences.edit();
                    e.putLong(FILTER_CHANGE, time);
                    e.commit();
                    Log.i(TAG, "Stored " + time + " to shared preferences for last filter change");
                    updateFilterChangeDate();
                }

                return false;
            }
        });

        LocalBroadcastManager.getInstance(this).registerReceiver(temperatureUpdate, new IntentFilter("temperature"));
        LocalBroadcastManager.getInstance(this).registerReceiver(waterlevelUpdate, new IntentFilter("waterlevel"));

        updateFilterChangeDate();
        updateIronAdditionDate();
        updateWaterChangeDate();

        m_exitHandler.postDelayed(exitViewOnTimeout, VIEW_TIMEOUT);
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy");
        super.onDestroy();
    }

    private void updateFilterChangeDate()
    {
        Calendar c = Calendar.getInstance();
        Long item = m_preferences.getLong("FilterChange", 0);
        c.setTimeInMillis(item);
        SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d");
        m_textViewFilterChange.setText(df.format(c.getTime()));
    }

    private void updateWaterChangeDate()
    {
        Calendar c = Calendar.getInstance();
        Long item = m_preferences.getLong("WaterChange", 0);
        Log.d(TAG, "Got " + item + " for last water change millis");
        c.setTimeInMillis(item);
        SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d");
        m_textViewWaterChange.setText(df.format(c.getTime()));
    }

    private void updateIronAdditionDate()
    {
        Calendar c = Calendar.getInstance();
        Long item = m_preferences.getLong("IronAddition", 0);
        c.setTimeInMillis(item);
        SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d");
        m_textViewIronAddition.setText(df.format(c.getTime()));
    }

    public void exitView(View view)
    {
        Log.d(TAG, "Closing view");
        m_exitHandler.removeCallbacks(exitViewOnTimeout);
        finish();
    }

    private BroadcastReceiver temperatureUpdate = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            Double value = intent.getDoubleExtra("ACTION", 0.0);
            m_textViewTemperature.setText(value.toString() + " \u2109");
        }
    };

    private BroadcastReceiver waterlevelUpdate = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            Integer value = intent.getIntExtra("ACTION", 0);
            String text;
            if (value > 2760)
                text = "full";
            else if (value > 2750)
                text = "-1 cm";
            else if (value > 2730)
                text = "-2 cm";
            else
                text = value.toString();

            m_textViewWaterLevel.setText(text);
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
    }

    private Runnable exitViewOnTimeout = new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "Closing view due to timeout handler");
            finish();
        }
    };
}

Logging shows that a valid millis value is stored in the Long in the OnTouchListener, which is called when I touch the TextView. Every call to updateWaterChangeDate() logs 0 for item and the Date is always the 1st of 1970.

2019-06-22 09:20:20.483 2614-2614/com.home.pete.aquarium I/DataViewActivity: Stored 1561213220471 to shared preferences for last water change
2019-06-22 09:20:20.484 2614-2614/com.home.pete.aquarium D/DataViewActivity: Got 0 for last water change millis
...
2019-06-22 09:20:25.647 2614-2614/com.home.pete.aquarium D/DataViewActivity: onDestroy
2019-06-22 09:20:26.710 2614-2614/com.home.pete.aquarium D/MainActivity: Viewing settings
2019-06-22 09:20:26.737 2614-2614/com.home.pete.aquarium D/DataViewActivity: onCreate
2019-06-22 09:20:26.834 2614-2614/com.home.pete.aquarium D/DataViewActivity: Got 0 for last water change millis

The method getLong returns a long, the second parameter to the method you're calling is not a reference to be filled, but the default value to be returned in case the preference is not found.

Your code is simply not checking the return value from shared preferences.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM