OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.webapps; | 5 package org.chromium.chrome.browser.webapps; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.SharedPreferences; | 8 import android.content.SharedPreferences; |
9 import android.os.SystemClock; | 9 import android.os.SystemClock; |
10 import android.util.Log; | 10 import android.util.Log; |
11 | 11 |
| 12 import org.chromium.base.ContextUtils; |
12 import org.chromium.base.ThreadUtils; | 13 import org.chromium.base.ThreadUtils; |
13 import org.chromium.base.VisibleForTesting; | 14 import org.chromium.base.VisibleForTesting; |
14 import org.chromium.base.metrics.RecordHistogram; | 15 import org.chromium.base.metrics.RecordHistogram; |
| 16 import org.chromium.webapk.lib.common.WebApkConstants; |
15 | 17 |
16 import java.util.ArrayList; | 18 import java.util.ArrayList; |
17 import java.util.HashSet; | 19 import java.util.HashSet; |
18 import java.util.List; | 20 import java.util.List; |
19 import java.util.Set; | 21 import java.util.Set; |
20 import java.util.concurrent.TimeUnit; | 22 import java.util.concurrent.TimeUnit; |
21 | 23 |
22 /** | 24 /** |
23 * Manages a rotating LRU buffer of WebappActivities to assign webapps to. | 25 * Before Lollipop, the only way to create multiple retargetable instances of th
e same Activity |
| 26 * was to explicitly define them in the Manifest. Given that the user can poten
tially have an |
| 27 * unlimited number of shortcuts for launching these Activities, we have to acti
vely assign |
| 28 * shortcuts when they launch. Activities are reused in order of when they were
last used, with |
| 29 * the least recently used ones reassigned first. |
24 * | 30 * |
25 * In order to accommodate a limited number of WebappActivities with a potential
ly unlimited number | 31 * In order to accommodate a limited number of WebappActivities with a potential
ly unlimited number |
26 * of webapps, we have to rotate the available WebappActivities between the weba
pps we start up. | 32 * of webapps, we have to rotate the available WebappActivities between the weba
pps we start up. |
27 * Activities are reused in order of when they were last used, with the least re
cently used | 33 * Activities are reused in order of when they were last used, with the least re
cently used |
28 * ones culled first. | 34 * ones culled first. |
29 * | 35 * |
30 * It is impossible to know whether Tasks have been removed from the Recent Task
list without the | 36 * It is impossible to know whether Tasks have been removed from the Recent Task
list without the |
31 * GET_TASKS permission. As a result, the list of Activities inside the Recent
Task list will | 37 * GET_TASKS permission. As a result, the list of Activities inside the Recent
Task list will |
32 * be highly unlikely to match the list maintained in memory. Instead, we store
the mapping as it | 38 * be highly unlikely to match the list maintained in memory. Instead, we store
the mapping as it |
33 * was the last time we changed it, which allows us to launch webapps in the Web
appActivity they | 39 * was the last time we changed it, which allows us to launch webapps in the Web
appActivity they |
(...skipping 22 matching lines...) Expand all Loading... |
56 // Don't ever change this. 10 is enough for everyone. | 62 // Don't ever change this. 10 is enough for everyone. |
57 static final int NUM_WEBAPP_ACTIVITIES = 10; | 63 static final int NUM_WEBAPP_ACTIVITIES = 10; |
58 | 64 |
59 // A sanity check limit to ensure that we aren't reading an unreasonable num
ber of preferences. | 65 // A sanity check limit to ensure that we aren't reading an unreasonable num
ber of preferences. |
60 // This number is different from above because the number of WebappActivitie
s available may | 66 // This number is different from above because the number of WebappActivitie
s available may |
61 // change. | 67 // change. |
62 static final int MAX_WEBAPP_ACTIVITIES_EVER = 100; | 68 static final int MAX_WEBAPP_ACTIVITIES_EVER = 100; |
63 | 69 |
64 // Don't ever change the package. Left for backwards compatibility. | 70 // Don't ever change the package. Left for backwards compatibility. |
65 @VisibleForTesting | 71 @VisibleForTesting |
66 static final String PREF_PACKAGE = "com.google.android.apps.chrome.webapps"; | 72 static final String PREF_PACKAGE[] = {"com.google.android.apps.chrome.webapp
s", |
67 static final String PREF_NUM_SAVED_ENTRIES = "ActivityAssigner.numSavedEntri
es"; | 73 "com.google.android.apps.chrome.webapps.webapk"}; |
68 static final String PREF_ACTIVITY_INDEX = "ActivityAssigner.activityIndex"; | 74 |
69 static final String PREF_WEBAPP_ID = "ActivityAssigner.webappId"; | 75 static final String PREF_NUM_SAVED_ENTRIES[] = {"ActivityAssigner.numSavedEn
tries", |
| 76 "ActivityAssigner.numSavedEntries.webapk"}; |
| 77 static final String PREF_ACTIVITY_INDEX[] = {"ActivityAssigner.activityIndex
", |
| 78 "ActivityAssigner.activityIndex.webapk"}; |
| 79 static final String PREF_WEBAPP_ID[] = {"ActivityAssigner.webappId", |
| 80 "ActivityAssigner.webappId.webapk"}; |
70 | 81 |
71 static final int INVALID_ACTIVITY_INDEX = -1; | 82 static final int INVALID_ACTIVITY_INDEX = -1; |
| 83 static final int WEBAPP_ACTIVITY_INDEX = 0; |
| 84 static final int WEBAPK_ACTIVITY_INDEX = 1; |
| 85 static final int ACTIVITY_TYPE_COUNT = 2; |
72 | 86 |
73 private static ActivityAssigner sInstance; | 87 private static final Object LOCK = new Object(); |
| 88 private static List<ActivityAssigner> sInstances; |
74 | 89 |
75 private final Context mContext; | 90 private final Context mContext; |
76 private final List<ActivityEntry> mActivityList; | 91 private final List<ActivityEntry> mActivityList; |
| 92 // The type index of the Activities managed. Either {@link WEBAPP_ACTIVITY_I
NDEX} or |
| 93 // {@link WEBAPK_ACTIVITY_INDEX}. |
| 94 private final int mActivityTypeIndex; |
77 | 95 |
78 /** | 96 /** |
79 * Pre-load shared prefs to avoid being blocked on the | 97 * Pre-load shared prefs to avoid being blocked on the |
80 * disk access async task in the future. | 98 * disk access async task in the future. |
81 */ | 99 */ |
82 public static void warmUpSharedPrefs(Context context) { | 100 public static void warmUpSharedPrefs(Context context) { |
83 context.getSharedPreferences(PREF_PACKAGE, Context.MODE_PRIVATE); | 101 for (int i = 0; i < ACTIVITY_TYPE_COUNT; ++i) { |
| 102 context.getSharedPreferences(PREF_PACKAGE[i], Context.MODE_PRIVATE); |
| 103 } |
84 } | 104 } |
85 | 105 |
86 static class ActivityEntry { | 106 static class ActivityEntry { |
87 final int mActivityIndex; | 107 final int mActivityIndex; |
88 final String mWebappId; | 108 final String mWebappId; |
89 | 109 |
90 ActivityEntry(int activity, String webapp) { | 110 ActivityEntry(int activity, String webapp) { |
91 mActivityIndex = activity; | 111 mActivityIndex = activity; |
92 mWebappId = webapp; | 112 mWebappId = webapp; |
93 } | 113 } |
94 } | 114 } |
95 | 115 |
96 /** | 116 /** |
97 * Returns the singleton instance, creating it if necessary. | 117 * Returns the singleton instance, creating it if necessary. |
| 118 * @param webappId The app ID. |
98 */ | 119 */ |
99 public static ActivityAssigner instance(Context context) { | 120 public static ActivityAssigner instance(String webappId) { |
100 ThreadUtils.assertOnUiThread(); | 121 ThreadUtils.assertOnUiThread(); |
101 if (sInstance == null) { | 122 synchronized (LOCK) { |
102 sInstance = new ActivityAssigner(context); | 123 if (sInstances == null) { |
| 124 sInstances = new ArrayList<ActivityAssigner>(ACTIVITY_TYPE_COUNT
); |
| 125 for (int i = 0; i < ACTIVITY_TYPE_COUNT; ++i) { |
| 126 sInstances.add(new ActivityAssigner(i)); |
| 127 } |
| 128 } |
103 } | 129 } |
104 return sInstance; | 130 return sInstances.get(ActivityAssigner.getIndex(webappId)); |
105 } | 131 } |
106 | 132 |
107 private ActivityAssigner(Context context) { | 133 private ActivityAssigner(int activityTypeIndex) { |
108 mContext = context.getApplicationContext(); | 134 mContext = ContextUtils.getApplicationContext(); |
| 135 mActivityTypeIndex = activityTypeIndex; |
109 mActivityList = new ArrayList<ActivityEntry>(); | 136 mActivityList = new ArrayList<ActivityEntry>(); |
110 | |
111 restoreActivityList(); | 137 restoreActivityList(); |
112 } | 138 } |
113 | 139 |
114 /** | 140 /** |
115 * Assigns the webapp with the given ID to one of the available WebappActivi
ties. | 141 * Assigns the app with the given ID to one of the available Activity instan
ces. |
116 * If we know that the webapp was previously launched in one of the Activiti
es, re-use it. | 142 * If we know that the app was previously launched in one of the Activities,
re-use it. |
117 * Otherwise, take the least recently used WebappActivity ID and use that. | 143 * Otherwise, take the least recently used ID and use that. |
118 * @param webappId ID of the webapp. | 144 * @param webappId ID of the webapp. |
119 * @return Index of the Activity to use for the webapp. | 145 * @return Index of the Activity to use for the webapp. |
120 */ | 146 */ |
121 int assign(String webappId) { | 147 int assign(String webappId) { |
122 // Reuse a running Activity with the same ID, if it exists. | 148 // Reuse a running Activity with the same ID, if it exists. |
123 int activityIndex = checkIfAssigned(webappId); | 149 int activityIndex = checkIfAssigned(webappId); |
124 | 150 |
125 // Allocate the one in the front of the list. | 151 // Allocate the one in the front of the list. |
126 if (activityIndex == INVALID_ACTIVITY_INDEX) { | 152 if (activityIndex == INVALID_ACTIVITY_INDEX) { |
127 activityIndex = mActivityList.get(0).mActivityIndex; | 153 activityIndex = mActivityList.get(0).mActivityIndex; |
128 ActivityEntry newEntry = new ActivityEntry(activityIndex, webappId); | 154 ActivityEntry newEntry = new ActivityEntry(activityIndex, webappId); |
129 mActivityList.set(0, newEntry); | 155 mActivityList.set(0, newEntry); |
130 } | 156 } |
131 | 157 |
132 markActivityUsed(activityIndex, webappId); | 158 markActivityUsed(activityIndex, webappId); |
133 return activityIndex; | 159 return activityIndex; |
134 } | 160 } |
135 | 161 |
136 /** | 162 /** |
| 163 * Returns {@link WEBAPP_ACTIVITY_INDEX} for WebappActivity, {@link WEBAPK_A
CTIVITY_INDEX} for |
| 164 * WebApkActivity whose webappId starts with "webapk:". |
| 165 */ |
| 166 static int getIndex(String webappId) { |
| 167 return webappId.startsWith(WebApkConstants.WEBAPK_ID_PREFIX) ? WEBAPK_AC
TIVITY_INDEX |
| 168 : WEBAPP_ACTIVITY_INDEX; |
| 169 } |
| 170 |
| 171 /** |
137 * Checks if the webapp with the given ID has been assigned to an Activity a
lready. | 172 * Checks if the webapp with the given ID has been assigned to an Activity a
lready. |
138 * @param webappId ID of the webapp being displayed. | 173 * @param webappId ID of the webapp being displayed. |
139 * @return Index of the Activity for the webapp if assigned, INVALID_ACTIVIT
Y_INDEX otherwise. | 174 * @return Index of the Activity for the webapp if assigned, INVALID_ACTIVIT
Y_INDEX otherwise. |
140 */ | 175 */ |
141 int checkIfAssigned(String webappId) { | 176 int checkIfAssigned(String webappId) { |
142 if (webappId == null) { | 177 if (webappId == null) { |
143 return INVALID_ACTIVITY_INDEX; | 178 return INVALID_ACTIVITY_INDEX; |
144 } | 179 } |
145 | 180 |
146 // Go backwards in the queue to catch more recent instances of any dupli
cated webapps. | 181 // Go backwards in the queue to catch more recent instances of any dupli
cated webapps. |
147 for (int i = mActivityList.size() - 1; i >= 0; i--) { | 182 for (int i = mActivityList.size() - 1; i >= 0; i--) { |
148 if (webappId.equals(mActivityList.get(i).mWebappId)) { | 183 if (webappId.equals(mActivityList.get(i).mWebappId)) { |
149 return mActivityList.get(i).mActivityIndex; | 184 return mActivityList.get(i).mActivityIndex; |
150 } | 185 } |
151 } | 186 } |
152 return INVALID_ACTIVITY_INDEX; | 187 return INVALID_ACTIVITY_INDEX; |
153 } | 188 } |
154 | 189 |
155 /** | 190 /** |
156 * Moves a WebappActivity to the back of the queue, indicating that the Weba
pp is still in use | 191 * Moves an Activity to the back of the queue, indicating that the app is st
ill in use and |
157 * and shouldn't be killed. | 192 * shouldn't be killed. |
158 * @param activityIndex Index of the WebappActivity. | 193 * @param activityIndex Index of the Activity in the LRU buffer. |
159 * @param webappId ID of the webapp being shown in the WebappActivity. | 194 * @param webappId The ID of the app being shown in the Activity. |
160 */ | 195 */ |
161 void markActivityUsed(int activityIndex, String webappId) { | 196 void markActivityUsed(int activityIndex, String webappId) { |
162 // Find the entry corresponding to the Activity. | 197 // Find the entry corresponding to the Activity. |
163 int elementIndex = findActivityElement(activityIndex); | 198 int elementIndex = findActivityElement(activityIndex); |
164 | 199 |
165 if (elementIndex == -1) { | 200 if (elementIndex == -1) { |
166 Log.e(TAG, "Failed to find WebappActivity entry: " + activityIndex +
", " + webappId); | 201 Log.e(TAG, "Failed to find WebappActivity entry: " + activityIndex +
", " + webappId); |
167 return; | 202 return; |
168 } | 203 } |
169 | 204 |
170 // We have to reassign the webapp ID in case WebappActivities get repurp
osed. | 205 // We have to reassign the app ID in case Activities get repurposed. |
171 ActivityEntry updatedEntry = new ActivityEntry(activityIndex, webappId); | 206 ActivityEntry updatedEntry = new ActivityEntry(activityIndex, webappId); |
172 mActivityList.remove(elementIndex); | 207 mActivityList.remove(elementIndex); |
173 mActivityList.add(updatedEntry); | 208 mActivityList.add(updatedEntry); |
174 storeActivityList(); | 209 storeActivityList(); |
175 } | 210 } |
176 | 211 |
177 /** | 212 /** |
178 * Finds the index of the ActivityElement corresponding to the given activit
yIndex. | 213 * Finds the index of the ActivityElement corresponding to the given activit
yIndex. |
179 * @param activityIndex Index of the activity to find. | 214 * @param activityIndex Index of the activity to find. |
180 * @return The index of the ActivityElement in the activity list, or -1 if i
t couldn't be found. | 215 * @return The index of the ActivityElement in the activity list, or -1 if i
t couldn't be found. |
181 */ | 216 */ |
182 private int findActivityElement(int activityIndex) { | 217 private int findActivityElement(int activityIndex) { |
183 for (int elementIndex = 0; elementIndex < mActivityList.size(); elementI
ndex++) { | 218 for (int elementIndex = 0; elementIndex < mActivityList.size(); elementI
ndex++) { |
184 if (mActivityList.get(elementIndex).mActivityIndex == activityIndex)
{ | 219 if (mActivityList.get(elementIndex).mActivityIndex == activityIndex)
{ |
185 return elementIndex; | 220 return elementIndex; |
186 } | 221 } |
187 } | 222 } |
188 return -1; | 223 return -1; |
189 } | 224 } |
190 | 225 |
191 /** | 226 /** |
192 * Returns the current mapping between Activities and webapps. | 227 * Returns the current mapping between Activities and apps. |
193 */ | 228 */ |
194 @VisibleForTesting | 229 @VisibleForTesting |
195 List<ActivityEntry> getEntries() { | 230 List<ActivityEntry> getEntries() { |
196 return mActivityList; | 231 return mActivityList; |
197 } | 232 } |
198 | 233 |
199 /** | 234 /** |
200 * Restores/creates the mapping between webapps and WebappActivities. | 235 * Returns the type index of the Activities managed. |
| 236 */ |
| 237 @VisibleForTesting |
| 238 int getActivityTypeIndex() { |
| 239 return mActivityTypeIndex; |
| 240 } |
| 241 |
| 242 /** |
| 243 * Restores/creates the mapping between apps and activities. |
201 * The logic is slightly complicated to future-proof against situations wher
e the number of | 244 * The logic is slightly complicated to future-proof against situations wher
e the number of |
202 * WebappActivities is changed. | 245 * Activity is changed. |
203 */ | 246 */ |
204 private void restoreActivityList() { | 247 private void restoreActivityList() { |
205 boolean isMapDirty = false; | 248 boolean isMapDirty = false; |
206 mActivityList.clear(); | 249 mActivityList.clear(); |
207 | 250 |
208 // Create a Set of indices corresponding to every possible Activity. | 251 // Create a Set of indices corresponding to every possible Activity. |
209 // As ActivityEntries are read, they are and removed from this list to i
ndicate that the | 252 // As ActivityEntries are read, they are and removed from this list to i
ndicate that the |
210 // Activity has already been assigned. | 253 // Activity has already been assigned. |
211 Set<Integer> availableWebapps = new HashSet<Integer>(); | 254 Set<Integer> availableWebapps = new HashSet<Integer>(); |
212 for (int i = 0; i < NUM_WEBAPP_ACTIVITIES; ++i) { | 255 for (int i = 0; i < NUM_WEBAPP_ACTIVITIES; ++i) { |
213 availableWebapps.add(i); | 256 availableWebapps.add(i); |
214 } | 257 } |
215 | 258 |
216 // Restore any entries that were previously saved. If it seems that the
preferences have | 259 // Restore any entries that were previously saved. If it seems that the
preferences have |
217 // been corrupted somehow, just discard the whole map. | 260 // been corrupted somehow, just discard the whole map. |
218 SharedPreferences prefs = mContext.getSharedPreferences(PREF_PACKAGE, Co
ntext.MODE_PRIVATE); | 261 SharedPreferences prefs = mContext.getSharedPreferences(PREF_PACKAGE[mAc
tivityTypeIndex], |
| 262 Context.MODE_PRIVATE); |
219 try { | 263 try { |
220 long time = SystemClock.elapsedRealtime(); | 264 long time = SystemClock.elapsedRealtime(); |
221 final int numSavedEntries = prefs.getInt(PREF_NUM_SAVED_ENTRIES, 0); | 265 final int numSavedEntries = prefs.getInt(PREF_NUM_SAVED_ENTRIES[mAct
ivityTypeIndex], 0); |
222 try { | 266 try { |
223 RecordHistogram.recordTimesHistogram("Android.StrictMode.WebappS
haredPrefs", | 267 RecordHistogram.recordTimesHistogram("Android.StrictMode.WebappS
haredPrefs", |
224 SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECO
NDS); | 268 SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECO
NDS); |
225 } catch (UnsatisfiedLinkError error) { | 269 } catch (UnsatisfiedLinkError error) { |
226 // Intentionally ignored - it's ok to miss recording the metric
occasionally. | 270 // Intentionally ignored - it's ok to miss recording the metric
occasionally. |
227 } | 271 } |
228 if (numSavedEntries <= NUM_WEBAPP_ACTIVITIES) { | 272 if (numSavedEntries <= NUM_WEBAPP_ACTIVITIES) { |
229 for (int i = 0; i < numSavedEntries; ++i) { | 273 for (int i = 0; i < numSavedEntries; ++i) { |
230 String currentActivityIndexPref = PREF_ACTIVITY_INDEX + i; | 274 String currentActivityIndexPref = PREF_ACTIVITY_INDEX[mActiv
ityTypeIndex] + i; |
231 String currentWebappIdPref = PREF_WEBAPP_ID + i; | 275 String currentWebappIdPref = PREF_WEBAPP_ID[mActivityTypeInd
ex] + i; |
232 | 276 |
233 int activityIndex = prefs.getInt(currentActivityIndexPref, i
); | 277 int activityIndex = prefs.getInt(currentActivityIndexPref, i
); |
234 String webappId = prefs.getString(currentWebappIdPref, null)
; | 278 String webappId = prefs.getString(currentWebappIdPref, null)
; |
235 ActivityEntry entry = new ActivityEntry(activityIndex, webap
pId); | 279 ActivityEntry entry = new ActivityEntry(activityIndex, webap
pId); |
236 | 280 |
237 if (availableWebapps.remove(entry.mActivityIndex)) { | 281 if (availableWebapps.remove(entry.mActivityIndex)) { |
238 mActivityList.add(entry); | 282 mActivityList.add(entry); |
239 } else { | 283 } else { |
240 // If the same activity was assigned to two different en
tries, or if the | 284 // If the same activity was assigned to two different en
tries, or if the |
241 // number of activities changed, discard it and mark tha
t it needs to be | 285 // number of activities changed, discard it and mark tha
t it needs to be |
242 // rewritten. | 286 // rewritten. |
243 isMapDirty = true; | 287 isMapDirty = true; |
244 } | 288 } |
245 } | 289 } |
246 } | 290 } |
247 } catch (ClassCastException exception) { | 291 } catch (ClassCastException exception) { |
248 // Something went wrong reading the preferences. Nuke everything. | 292 // Something went wrong reading the preferences. Nuke everything. |
249 mActivityList.clear(); | 293 mActivityList.clear(); |
250 availableWebapps.clear(); | 294 availableWebapps.clear(); |
251 for (int i = 0; i < NUM_WEBAPP_ACTIVITIES; ++i) { | 295 for (int i = 0; i < NUM_WEBAPP_ACTIVITIES; ++i) { |
252 availableWebapps.add(i); | 296 availableWebapps.add(i); |
253 } | 297 } |
254 } | 298 } |
255 | 299 |
256 // Add entries for any missing WebappActivities. | 300 // Add entries for any missing Activities. |
257 for (Integer availableIndex : availableWebapps) { | 301 for (Integer availableIndex : availableWebapps) { |
258 ActivityEntry entry = new ActivityEntry(availableIndex, null); | 302 ActivityEntry entry = new ActivityEntry(availableIndex, null); |
259 mActivityList.add(entry); | 303 mActivityList.add(entry); |
260 isMapDirty = true; | 304 isMapDirty = true; |
261 } | 305 } |
262 | 306 |
263 if (isMapDirty) { | 307 if (isMapDirty) { |
264 storeActivityList(); | 308 storeActivityList(); |
265 } | 309 } |
266 } | 310 } |
267 | 311 |
268 /** | 312 /** |
269 * Saves the mapping between webapps and WebappActivities. | 313 * Saves the mapping between apps and Activities. |
270 */ | 314 */ |
271 private void storeActivityList() { | 315 private void storeActivityList() { |
272 SharedPreferences prefs = mContext.getSharedPreferences(PREF_PACKAGE, Co
ntext.MODE_PRIVATE); | 316 SharedPreferences prefs = mContext.getSharedPreferences(PREF_PACKAGE[mAc
tivityTypeIndex], |
| 317 Context.MODE_PRIVATE); |
273 SharedPreferences.Editor editor = prefs.edit(); | 318 SharedPreferences.Editor editor = prefs.edit(); |
274 editor.clear(); | 319 editor.clear(); |
275 editor.putInt(PREF_NUM_SAVED_ENTRIES, mActivityList.size()); | 320 editor.putInt(PREF_NUM_SAVED_ENTRIES[mActivityTypeIndex], mActivityList.
size()); |
276 for (int i = 0; i < mActivityList.size(); ++i) { | 321 for (int i = 0; i < mActivityList.size(); ++i) { |
277 String currentActivityIndexPref = PREF_ACTIVITY_INDEX + i; | 322 String currentActivityIndexPref = PREF_ACTIVITY_INDEX[mActivityTypeI
ndex] + i; |
278 String currentWebappIdPref = PREF_WEBAPP_ID + i; | 323 String currentWebappIdPref = PREF_WEBAPP_ID[mActivityTypeIndex] + i; |
279 editor.putInt(currentActivityIndexPref, mActivityList.get(i).mActivi
tyIndex); | 324 editor.putInt(currentActivityIndexPref, mActivityList.get(i).mActivi
tyIndex); |
280 editor.putString(currentWebappIdPref, mActivityList.get(i).mWebappId
); | 325 editor.putString(currentWebappIdPref, mActivityList.get(i).mWebappId
); |
281 } | 326 } |
282 editor.apply(); | 327 editor.apply(); |
283 } | 328 } |
284 } | 329 } |
OLD | NEW |