1 /* 2 * Copyright (c) 2017 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.example.android.wearable.wear.messaging.util; 17 18 import android.content.Context; 19 import android.content.SharedPreferences; 20 import android.util.Log; 21 import com.example.android.wearable.wear.messaging.model.Chat; 22 import com.example.android.wearable.wear.messaging.model.Message; 23 import com.example.android.wearable.wear.messaging.model.Profile; 24 import com.google.gson.Gson; 25 import com.google.gson.JsonSyntaxException; 26 import java.io.IOException; 27 import java.util.ArrayList; 28 import java.util.Collections; 29 import java.util.HashSet; 30 import java.util.LinkedHashSet; 31 import java.util.List; 32 import java.util.Set; 33 34 /** 35 * SharedPreferencesHelper provides static methods to set, get, delete these objects. 36 * 37 * <p>The user's profile details and chat details are persisted in SharedPreferences to access 38 * across the app. 39 */ 40 public class SharedPreferencesHelper { 41 42 private static final String TAG = "SharedPreferencesHelper"; 43 44 private static Gson gson = new Gson(); 45 46 /** 47 * Returns logged in user or null if no user is logged in. 48 * 49 * @param context shared preferences context 50 * @return user profile 51 */ readUserFromJsonPref(Context context)52 public static Profile readUserFromJsonPref(Context context) { 53 SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.PREFS_NAME, 0); 54 String profileString = sharedPreferences.getString(Constants.PREFS_USER_KEY, null); 55 if (profileString == null) { 56 return null; 57 } 58 try { 59 return gson.fromJson(profileString, Profile.class); 60 } catch (JsonSyntaxException e) { 61 Log.e(TAG, "Could not parse user from shard preferences.", e); 62 return null; 63 } 64 } 65 66 /** 67 * Writes a {@link Profile} to json and stores it in preferences. 68 * 69 * @param context used to access {@link SharedPreferences} 70 * @param user to be stored in preferences 71 */ writeUserToJsonPref(Context context, Profile user)72 public static void writeUserToJsonPref(Context context, Profile user) { 73 SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.PREFS_NAME, 0); 74 SharedPreferences.Editor editor = sharedPreferences.edit(); 75 editor.putString(Constants.PREFS_USER_KEY, gson.toJson(user)); 76 editor.apply(); 77 } 78 79 /** 80 * Reads contacts from preferences. 81 * 82 * @param context used to access {@link SharedPreferences} 83 * @return contacts from preferences 84 */ readContactsFromJsonPref(Context context)85 public static List<Profile> readContactsFromJsonPref(Context context) { 86 try { 87 return getList(context, Profile.class, Constants.PREFS_CONTACTS_KEY); 88 } catch (JsonSyntaxException e) { 89 String logMessage = 90 "Could not read/unmarshall the list of contacts from shared preferences."; 91 Log.e(TAG, logMessage, e); 92 return Collections.emptyList(); 93 } 94 } 95 96 /** 97 * Writes a {@link List<Profile>} to json and stores it in preferences. 98 * 99 * @param context used to access {@link SharedPreferences} 100 * @param contacts to be stored in preferences 101 */ writeContactsToJsonPref(Context context, List<Profile> contacts)102 public static void writeContactsToJsonPref(Context context, List<Profile> contacts) { 103 setList(context, contacts, Constants.PREFS_CONTACTS_KEY); 104 } 105 106 /** 107 * Reads chats from preferences 108 * 109 * @param context used to access {@link SharedPreferences} 110 * @return chats from preferences 111 * @throws IOException if there is an error parsing the json from preferences 112 */ readChatsFromJsonPref(Context context)113 public static List<Chat> readChatsFromJsonPref(Context context) throws IOException { 114 try { 115 return getList(context, Chat.class, Constants.PREFS_CHATS_KEY); 116 } catch (JsonSyntaxException e) { 117 Log.e(TAG, "Could not read/unmarshall the list of chats from shared preferences", e); 118 return Collections.emptyList(); 119 } 120 } 121 122 /** 123 * Writes a {@link List<Chat>} to json and stores it in preferences. 124 * 125 * @param context used to access {@link SharedPreferences} 126 * @param chats to be stores in preferences 127 */ writeChatsToJsonPref(Context context, List<Chat> chats)128 public static void writeChatsToJsonPref(Context context, List<Chat> chats) { 129 Log.d(TAG, String.format("Saving %d chat(s)", chats.size())); 130 setList(context, chats, Constants.PREFS_CHATS_KEY); 131 } 132 133 /** 134 * Reads messages for a chat from preferences. 135 * 136 * @param context used to access {@link SharedPreferences} 137 * @param chatId for the chat the messages are from 138 * @return messages from preferences 139 */ readMessagesForChat(Context context, String chatId)140 public static List<Message> readMessagesForChat(Context context, String chatId) { 141 try { 142 return getList(context, Message.class, Constants.PREFS_MESSAGE_PREFIX + chatId); 143 } catch (JsonSyntaxException e) { 144 Log.e(TAG, "Could not read/unmarshall the list of messages from shared preferences", e); 145 return Collections.emptyList(); 146 } 147 } 148 149 /** 150 * Writes a {@link List<Message>} to json and stores it in preferences. 151 * 152 * @param context used to access {@link SharedPreferences} 153 * @param chat that the messages are from 154 * @param messages to be stored into preferences 155 */ writeMessagesForChatToJsonPref( Context context, Chat chat, List<Message> messages)156 public static void writeMessagesForChatToJsonPref( 157 Context context, Chat chat, List<Message> messages) { 158 setList(context, messages, Constants.PREFS_MESSAGE_PREFIX + chat.getId()); 159 } 160 161 /** 162 * Returns List of specified class from SharedPreferences (converts from string in 163 * SharedPreferences to class) 164 * 165 * @param context used for getting an instance of shared preferences 166 * @param clazz the class that the strings will be unmarshalled into 167 * @param key the key in shared preferences to access the string set 168 * @param <T> the type of object that will be in the returned list, should be the same as the 169 * clazz that was supplied 170 * @return a list of <T> objects that were stored in shared preferences. Returns an empty list 171 * if no data is available. 172 */ getList(Context context, Class<T> clazz, String key)173 private static <T> List<T> getList(Context context, Class<T> clazz, String key) 174 throws JsonSyntaxException { 175 SharedPreferences sharedPreferences = 176 context.getSharedPreferences(Constants.PREFS_NAME, Context.MODE_PRIVATE); 177 Set<String> contactsSet = sharedPreferences.getStringSet(key, new HashSet<String>()); 178 if (contactsSet.isEmpty()) { 179 // Favoring mutability of the list over Collections.emptyList(). 180 return new ArrayList<>(); 181 } 182 List<T> list = new ArrayList<>(contactsSet.size()); 183 for (String contactString : contactsSet) { 184 list.add(gson.fromJson(contactString, clazz)); 185 } 186 return list; 187 } 188 189 /** 190 * Sets a List of specified class in SharedPreferences (converts from List of class to string 191 * for SharedPreferences) 192 * 193 * @param context used for getting an instance of shared preferences 194 * @param list of <T> object that need to be persisted 195 * @param key the key in shared preferences which the string set will be stored 196 * @param <T> type the of object we will be marshalling and persisting 197 */ setList(Context context, List<T> list, String key)198 private static <T> void setList(Context context, List<T> list, String key) { 199 SharedPreferences sharedPreferences = 200 context.getSharedPreferences(Constants.PREFS_NAME, Context.MODE_PRIVATE); 201 SharedPreferences.Editor editor = sharedPreferences.edit(); 202 203 Set<String> strings = new LinkedHashSet<>(list.size()); 204 for (T t : list) { 205 strings.add(gson.toJson(t)); 206 } 207 editor.putStringSet(key, strings); 208 editor.apply(); 209 } 210 } 211