storymaker / app / src / org / storymaker / app / BaseHomeActivity.java @ 5debefcb
History | View | Annotate | Download (42 KB)
1 |
package org.storymaker.app; |
---|---|
2 |
|
3 |
import android.Manifest; |
4 |
import android.app.AlertDialog; |
5 |
import android.app.ProgressDialog; |
6 |
import android.content.ComponentName; |
7 |
import android.content.Context; |
8 |
import android.content.DialogInterface; |
9 |
import android.content.Intent; |
10 |
import android.content.SharedPreferences; |
11 |
import android.content.pm.PackageManager; |
12 |
import android.net.Uri; |
13 |
import android.os.AsyncTask; |
14 |
import android.os.Bundle; |
15 |
import android.preference.PreferenceManager; |
16 |
import android.support.v4.app.ActivityCompat; |
17 |
import android.support.v4.view.ViewPager; |
18 |
import android.support.v7.widget.RecyclerView; |
19 |
import android.util.Log; |
20 |
import android.view.Menu; |
21 |
import android.view.MenuItem; |
22 |
import android.widget.Toast; |
23 |
|
24 |
import com.hannesdorfmann.sqlbrite.dao.DaoManager; |
25 |
|
26 |
import net.hockeyapp.android.CrashManager; |
27 |
import net.hockeyapp.android.CrashManagerListener; |
28 |
import net.hockeyapp.android.UpdateManager; |
29 |
import net.sqlcipher.Cursor; |
30 |
import net.sqlcipher.database.SQLiteDatabase; |
31 |
import net.sqlcipher.database.SQLiteDatabaseHook; |
32 |
|
33 |
import org.apache.commons.io.FileUtils; |
34 |
import org.apache.commons.io.FilenameUtils; |
35 |
import org.apache.commons.io.filefilter.WildcardFileFilter; |
36 |
import org.apache.commons.lang3.StringUtils; |
37 |
import org.storymaker.app.model.Project; |
38 |
import org.storymaker.app.server.LoginActivity; |
39 |
import org.storymaker.app.server.ServerManager; |
40 |
import org.storymaker.app.ui.SlidingTabLayout; |
41 |
|
42 |
import java.io.BufferedReader; |
43 |
import java.io.File; |
44 |
import java.io.IOException; |
45 |
import java.io.InputStreamReader; |
46 |
import java.util.ArrayList; |
47 |
import java.util.HashMap; |
48 |
import java.util.List; |
49 |
|
50 |
import info.guardianproject.netcipher.proxy.OrbotHelper; |
51 |
import rx.functions.Action1; |
52 |
import scal.io.liger.JsonHelper; |
53 |
import scal.io.liger.MainActivity; |
54 |
import scal.io.liger.StorageHelper; |
55 |
import scal.io.liger.StorymakerIndexManager; |
56 |
import scal.io.liger.model.ContentPackMetadata; |
57 |
import scal.io.liger.model.StoryPathLibrary; |
58 |
import scal.io.liger.model.sqlbrite.AvailableIndexItem; |
59 |
import scal.io.liger.model.sqlbrite.AvailableIndexItemDao; |
60 |
import scal.io.liger.model.sqlbrite.ExpansionIndexItem; |
61 |
import scal.io.liger.model.sqlbrite.InstalledIndexItem; |
62 |
import scal.io.liger.model.sqlbrite.InstalledIndexItemDao; |
63 |
import scal.io.liger.model.sqlbrite.InstanceIndexItem; |
64 |
import scal.io.liger.model.sqlbrite.InstanceIndexItemDao; |
65 |
import scal.io.liger.model.sqlbrite.QueueItemDao; |
66 |
import timber.log.Timber; |
67 |
|
68 |
/**
|
69 |
* Created by josh on 12/18/15.
|
70 |
*/
|
71 |
public abstract class BaseHomeActivity extends BaseActivity { |
72 |
|
73 |
protected ProgressDialog mLoading;
|
74 |
protected ArrayList<Project> mListProjects; |
75 |
protected RecyclerView mRecyclerView;
|
76 |
|
77 |
protected ViewPager mViewPager;
|
78 |
protected SlidingTabLayout mSlidingTabLayout;
|
79 |
protected String[] mTabMenu; |
80 |
|
81 |
protected boolean loggedIn; |
82 |
|
83 |
// new stuff
|
84 |
protected InstanceIndexItemDao instanceIndexItemDao;
|
85 |
protected AvailableIndexItemDao availableIndexItemDao;
|
86 |
protected InstalledIndexItemDao installedIndexItemDao;
|
87 |
protected QueueItemDao queueItemDao;
|
88 |
protected DaoManager daoManager;
|
89 |
protected int dbVersion = 2; |
90 |
|
91 |
protected HashMap<String, ArrayList<Thread>> downloadThreads = new HashMap<String, ArrayList<Thread>>(); |
92 |
|
93 |
public void removeThreads(String id) { |
94 |
if (downloadThreads.containsKey(id)) {
|
95 |
downloadThreads.remove(id); |
96 |
} |
97 |
} |
98 |
|
99 |
public BaseHomeActivity() {
|
100 |
|
101 |
instanceIndexItemDao = new InstanceIndexItemDao();
|
102 |
availableIndexItemDao = new AvailableIndexItemDao();
|
103 |
installedIndexItemDao = new InstalledIndexItemDao();
|
104 |
queueItemDao = new QueueItemDao();
|
105 |
|
106 |
daoManager = new DaoManager(BaseHomeActivity.this, "Storymaker.db", dbVersion, instanceIndexItemDao, availableIndexItemDao, installedIndexItemDao, queueItemDao); |
107 |
daoManager.setLogging(false);
|
108 |
|
109 |
//Log.d("BaseHomeActivity", "DB version "+daoManager.getVersion());
|
110 |
|
111 |
|
112 |
} |
113 |
|
114 |
public String[] getMenu(String menu_type) { |
115 |
|
116 |
//This Method Transposes between an arrays.xml array of ids to build the catalog menu
|
117 |
// and their strings.xml display name counterparts
|
118 |
// the idea is the ids can be consistent (they will be part of database queries),
|
119 |
// whereas the Menu tab names can be localized
|
120 |
//
|
121 |
// ex: in arrays.xml
|
122 |
//
|
123 |
// <string-array name="catalog_menu_ids">
|
124 |
// <item>catalog</item>
|
125 |
// <item>guides</item>
|
126 |
// <item>lessons</item>
|
127 |
// <item>templates</item>
|
128 |
// </string-array>
|
129 |
//
|
130 |
// ex: in strings.xml
|
131 |
//
|
132 |
// <string name="catalog_menu_catalog">Catalog</string>
|
133 |
// <string name="catalog_menu_guides">Guides</string>
|
134 |
// <string name="catalog_menu_lessons">Lessons</string>
|
135 |
// <string name="catalog_menu_templates">Templates</string>
|
136 |
//
|
137 |
|
138 |
int menuId = getResources().getIdentifier(menu_type + "_menu_ids", "array", getApplicationContext().getPackageName()); |
139 |
String[] menu_ids = getResources().getStringArray(menuId); |
140 |
String[] menu_names = new String[menu_ids.length]; |
141 |
|
142 |
for (int i=0; i<menu_ids.length; i++) { |
143 |
int id = getResources().getIdentifier("home_menu_" + menu_ids[i], "string", getApplicationContext().getPackageName()); |
144 |
String menu_name = getResources().getString(id);
|
145 |
menu_names[i] = menu_name; |
146 |
} |
147 |
|
148 |
//String s = getString(R.string.finished_downloading);
|
149 |
|
150 |
return menu_names;
|
151 |
|
152 |
} |
153 |
|
154 |
// added for testing
|
155 |
public void scroll(int position) { |
156 |
Timber.d("Scrolling to index item " + position);
|
157 |
mRecyclerView.scrollToPosition(position); |
158 |
} |
159 |
|
160 |
public static String parseInstanceDate(String filename) { |
161 |
// String jsonFilePath = storyPath.buildTargetPath(storyPath.getId() + "-instance-" + timeStamp.getTime() + ".json");
|
162 |
String[] splits = FilenameUtils.removeExtension(filename).split("-"); |
163 |
return splits[splits.length - 1]; // FIXME make more robust and move into liger |
164 |
} |
165 |
|
166 |
// copied this as a short term fix until we get loading cleanly split out from the liger sample app ui stuff
|
167 |
protected StoryPathLibrary initSPLFromJson(String json, String jsonPath) { |
168 |
if (json == null || json.equals("")) { // FIXME use StringUtils |
169 |
Toast.makeText(this, getString(R.string.home_content_missing), Toast.LENGTH_LONG).show();
|
170 |
finish(); |
171 |
return null; |
172 |
} |
173 |
|
174 |
ArrayList<String> referencedFiles = null; |
175 |
|
176 |
// should not need to insert dependencies into a saved instance
|
177 |
if (jsonPath.contains("instance")) { |
178 |
referencedFiles = new ArrayList<String>(); |
179 |
} else {
|
180 |
referencedFiles = JsonHelper.getInstancePaths(this);
|
181 |
} |
182 |
|
183 |
StoryPathLibrary storyPathLibrary = JsonHelper.deserializeStoryPathLibrary(json, jsonPath, referencedFiles, this, StoryMakerApp.getCurrentLocale().getLanguage());
|
184 |
|
185 |
if ((storyPathLibrary != null) && (storyPathLibrary.getCurrentStoryPathFile() != null)) { |
186 |
storyPathLibrary.loadStoryPathTemplate("CURRENT", false); |
187 |
} |
188 |
|
189 |
return storyPathLibrary;
|
190 |
} |
191 |
|
192 |
@Override
|
193 |
public void onCreate(Bundle savedInstanceState) { |
194 |
super.onCreate(savedInstanceState);
|
195 |
|
196 |
// copy index file
|
197 |
StorymakerIndexManager.copyAvailableIndex(this, false); // TODO: REPLACE THIS WITH INDEX DOWNLOAD (IF LOGGED IN) <- NEED TO COPY FILE FOR BASELINE CONTENT |
198 |
|
199 |
// initialize db
|
200 |
|
201 |
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); |
202 |
|
203 |
// version check (sqlite upgrade requires migration)
|
204 |
|
205 |
int appMigrationVersion = preferences.getInt("APP_MIGRATION_VERSION", 0); |
206 |
|
207 |
Timber.d("MIGRATION CHECK: " + appMigrationVersion + " vs. " + Constants.APP_MIGRATION_VERSION); |
208 |
|
209 |
if (appMigrationVersion != Constants.APP_MIGRATION_VERSION) {
|
210 |
|
211 |
Timber.d("MIGRATION REQUIRED, RE-ENCRYPTING DATABASE");
|
212 |
|
213 |
final boolean[] dbStatus = {false}; |
214 |
try {
|
215 |
SQLiteDatabaseHook dbHook = new SQLiteDatabaseHook() {
|
216 |
public void preKey(SQLiteDatabase database) { |
217 |
} |
218 |
public void postKey(SQLiteDatabase database) { |
219 |
Cursor cursor = database.rawQuery("PRAGMA cipher_migrate", new String[]{}); |
220 |
String value = ""; |
221 |
if (cursor != null) { |
222 |
cursor.moveToFirst(); |
223 |
value = cursor.getString(0);
|
224 |
cursor.close(); |
225 |
} |
226 |
|
227 |
// this result is currently ignored, checking if db is null instead
|
228 |
dbStatus[0] = Integer.valueOf(value) == 0; |
229 |
} |
230 |
}; |
231 |
|
232 |
File dbPath = getDatabasePath("sm.db"); |
233 |
Timber.d("MIGRATING DATABASE AT " + dbPath.getPath());
|
234 |
|
235 |
SQLiteDatabase sqldb = SQLiteDatabase.openOrCreateDatabase(dbPath, "foo", null, dbHook); |
236 |
if (sqldb != null) { |
237 |
Timber.d("MIGRATED DATABASE NOT NULL");
|
238 |
sqldb.close(); |
239 |
|
240 |
// update preferences if migration succeeded
|
241 |
|
242 |
preferences.edit().putInt("APP_MIGRATION_VERSION", Constants.APP_MIGRATION_VERSION).commit();
|
243 |
} else {
|
244 |
Timber.e("MIGRATED DATABASE IS NULL");
|
245 |
} |
246 |
} catch (Exception ex) { |
247 |
Timber.e("EXCEPTION WHILE MIGRATING DATABASE: " + ex.getMessage());
|
248 |
} |
249 |
} |
250 |
|
251 |
int availableIndexVersion = preferences.getInt("AVAILABLE_INDEX_VERSION", 0); |
252 |
|
253 |
Timber.d("VERSION CHECK: " + availableIndexVersion + " vs. " + scal.io.liger.Constants.AVAILABLE_INDEX_VERSION); |
254 |
|
255 |
if (availableIndexVersion != scal.io.liger.Constants.AVAILABLE_INDEX_VERSION) {
|
256 |
|
257 |
// load db from file
|
258 |
|
259 |
HashMap<String, scal.io.liger.model.ExpansionIndexItem> availableItemsFromFile = scal.io.liger.IndexManager.loadAvailableIdIndex(this); |
260 |
|
261 |
if (availableItemsFromFile.size() == 0) { |
262 |
Timber.d("NOTHING LOADED FROM AVAILABLE FILE");
|
263 |
} else {
|
264 |
for (scal.io.liger.model.ExpansionIndexItem item : availableItemsFromFile.values()) {
|
265 |
Timber.d("ADDING " + item.getExpansionId() + " TO DATABASE (AVAILABLE)"); |
266 |
availableIndexItemDao.addAvailableIndexItem(item, true); // replaces existing items, should trigger updates to installed items and table as needed |
267 |
|
268 |
// ugly solution to deal with the fact that the popup menu assumes there will be threads for an item we tried to download/install
|
269 |
ArrayList<Thread> noThreads = new ArrayList<Thread>(); |
270 |
downloadThreads.put(item.getExpansionId(), noThreads); |
271 |
|
272 |
} |
273 |
} |
274 |
|
275 |
// the following migration stuff is currently piggy-backing on the index update stuff
|
276 |
|
277 |
// if found, migrate installed index
|
278 |
|
279 |
File installedFile = new File(StorageHelper.getActualStorageDirectory(this), "installed_index.json"); |
280 |
|
281 |
if (installedFile.exists()) {
|
282 |
HashMap<String, scal.io.liger.model.ExpansionIndexItem> installedItemsFromFile = scal.io.liger.IndexManager.loadInstalledIdIndex(this); |
283 |
|
284 |
if (installedItemsFromFile.size() == 0) { |
285 |
Timber.d("NOTHING LOADED FROM INSTALLED INDEX FILE");
|
286 |
} else {
|
287 |
for (scal.io.liger.model.ExpansionIndexItem item : installedItemsFromFile.values()) {
|
288 |
Timber.d("ADDING " + item.getExpansionId() + " TO DATABASE (INSTALLED)"); |
289 |
installedIndexItemDao.addInstalledIndexItem(item, true); // replaces existing items, should trigger updates to installed items and table as needed |
290 |
} |
291 |
} |
292 |
|
293 |
installedFile.delete(); |
294 |
} else {
|
295 |
Timber.d("NO INSTALLED INDEX FILE");
|
296 |
} |
297 |
|
298 |
// if found, migrate instance index
|
299 |
|
300 |
File instanceFile = new File(StorageHelper.getActualStorageDirectory(this), "instance_index.json"); |
301 |
|
302 |
if (instanceFile.exists()) {
|
303 |
HashMap<String, scal.io.liger.model.InstanceIndexItem> instanceItemsFromFile = scal.io.liger.IndexManager.loadInstanceIndex(this); |
304 |
|
305 |
if (instanceItemsFromFile.size() == 0) { |
306 |
Timber.d("NOTHING LOADED FROM INSTANCE INDEX FILE");
|
307 |
} else {
|
308 |
for (scal.io.liger.model.InstanceIndexItem item : instanceItemsFromFile.values()) {
|
309 |
Timber.d("ADDING " + item.getInstanceFilePath() + " TO DATABASE (INSTANCE)"); |
310 |
instanceIndexItemDao.addInstanceIndexItem(item, true); // replaces existing items, should trigger updates to installed items and table as needed |
311 |
} |
312 |
} |
313 |
|
314 |
instanceFile.delete(); |
315 |
} else {
|
316 |
Timber.d("NO INSTANCE INDEX FILE");
|
317 |
} |
318 |
|
319 |
// update preferences
|
320 |
|
321 |
preferences.edit().putInt("AVAILABLE_INDEX_VERSION", scal.io.liger.Constants.AVAILABLE_INDEX_VERSION).commit();
|
322 |
|
323 |
if (getIntent() != null && getIntent().hasExtra("showlauncher")) { |
324 |
if (getIntent().getBooleanExtra("showlauncher", false)) { |
325 |
showLauncherIcon(); |
326 |
} |
327 |
} |
328 |
} |
329 |
|
330 |
|
331 |
|
332 |
// dumb test
|
333 |
|
334 |
// check values
|
335 |
availableIndexItemDao.getAvailableIndexItems().take(1).subscribe(new Action1<List<AvailableIndexItem>>() { |
336 |
|
337 |
@Override
|
338 |
public void call(List<AvailableIndexItem> expansionIndexItems) { |
339 |
|
340 |
// just process the list
|
341 |
|
342 |
for (ExpansionIndexItem item : expansionIndexItems) {
|
343 |
Timber.d("AVAILABLE ITEM " + item.getExpansionId() + ", TITLE: " + item.getTitle()); |
344 |
} |
345 |
} |
346 |
}); |
347 |
|
348 |
installedIndexItemDao.getInstalledIndexItems().take(1).subscribe(new Action1<List<InstalledIndexItem>>() { |
349 |
|
350 |
@Override
|
351 |
public void call(List<InstalledIndexItem> expansionIndexItems) { |
352 |
|
353 |
// just process the list
|
354 |
|
355 |
for (ExpansionIndexItem item : expansionIndexItems) {
|
356 |
Timber.d("INSTALLED ITEM " + item.getExpansionId() + ", TITLE: " + item.getTitle()); |
357 |
} |
358 |
} |
359 |
}); |
360 |
|
361 |
|
362 |
|
363 |
// file cleanup
|
364 |
File actualStorageDirectory = StorageHelper.getActualStorageDirectory(this); |
365 |
|
366 |
if (actualStorageDirectory != null) { |
367 |
JsonHelper.cleanup(actualStorageDirectory.getPath()); |
368 |
} else {
|
369 |
// this is an error, will deal with it below
|
370 |
} |
371 |
|
372 |
// default
|
373 |
loggedIn = false;
|
374 |
|
375 |
// set title bar as a reminder if test server is specified
|
376 |
//getActionBar().setTitle(Utils.getAppName(this));
|
377 |
|
378 |
if (actualStorageDirectory != null) { |
379 |
// NEW/TEMP
|
380 |
// DOWNLOAD AVAILABE INDEX FOR CURRENT USER AND SAVE TO TARGET FILE
|
381 |
// NEED TO ACCOUNT FOR POSSIBLE MISSING INDEX
|
382 |
IndexTask iTask = new IndexTask(this, true); // force download at startup (maybe only force on a timetable?) |
383 |
iTask.execute(); |
384 |
} else {
|
385 |
//show storage error message
|
386 |
new AlertDialog.Builder(this) |
387 |
.setTitle(Utils.getAppName(this))
|
388 |
.setIcon(android.R.drawable.ic_dialog_info) |
389 |
.setMessage(R.string.err_storage_not_available) |
390 |
.show(); |
391 |
} |
392 |
|
393 |
// we want to grab required updates without restarting the app
|
394 |
// integrate with index task
|
395 |
// if (!DownloadHelper.checkAndDownload(this)) {
|
396 |
// Toast.makeText(this, "Downloading content and/or updating installed files", Toast.LENGTH_LONG).show(); // FIXME move to strings.xml
|
397 |
// }
|
398 |
|
399 |
// i don't think we ever want to do this
|
400 |
// IndexManager.copyInstalledIndex(this);
|
401 |
|
402 |
//setContentView(R.layout.activity_home);
|
403 |
|
404 |
//mRecyclerView = (RecyclerView) findViewById(scal.io.liger.R.id.recyclerView);
|
405 |
//mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
406 |
|
407 |
//mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
|
408 |
//mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
409 |
// @Override
|
410 |
// public void onRefresh() {
|
411 |
// IndexTask iTask = new IndexTask(HomeActivity.this, true); // force download on manual refresh
|
412 |
// iTask.execute();
|
413 |
// }
|
414 |
//});
|
415 |
|
416 |
|
417 |
//mTabMenu = getMenu("home");
|
418 |
// action bar stuff
|
419 |
getActionBar().setDisplayHomeAsUpEnabled(true);
|
420 |
|
421 |
checkForTor(); |
422 |
|
423 |
checkForUpdates(); |
424 |
|
425 |
} |
426 |
|
427 |
|
428 |
public static void launchLiger(Context context, String splId, String instancePath, String splPath) { |
429 |
|
430 |
// TEMP - do we need to check files for anything besides the default library?
|
431 |
/*
|
432 |
if (!DownloadHelper.checkAllFiles(context)) { // FIXME the app should define these, not the library
|
433 |
Toast.makeText(context, "Please wait for the content pack to finish downloading", Toast.LENGTH_LONG).show(); // FIXME move to strings.xml
|
434 |
return;
|
435 |
}
|
436 |
*/
|
437 |
|
438 |
if ((splId != null) && (splId.equals("default_library"))) { // FIXME use StringUtils |
439 |
|
440 |
// initiate check/download for main/patch expansion files
|
441 |
boolean readyToOpen = StorymakerDownloadHelper.checkAndDownloadNew(context);
|
442 |
|
443 |
if (!readyToOpen) {
|
444 |
// if file is being downloaded, don't open
|
445 |
Timber.d("CURRENTLY DOWNLOADING FILE");
|
446 |
|
447 |
Toast.makeText(context, context.getString(R.string.home_please_wait), Toast.LENGTH_LONG).show(); |
448 |
return;
|
449 |
} |
450 |
|
451 |
} |
452 |
|
453 |
Intent ligerIntent = new Intent(context, MainActivity.class);
|
454 |
ligerIntent.putExtra(MainActivity.INTENT_KEY_WINDOW_TITLE, Utils.getAppName(context)); |
455 |
String lang = StoryMakerApp.getCurrentLocale().getLanguage();
|
456 |
ligerIntent.putExtra("lang", lang);
|
457 |
|
458 |
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); |
459 |
int pslideduration = Integer.parseInt(settings.getString("pslideduration", "5")); |
460 |
ligerIntent.putExtra("photo_essay_slide_duration", pslideduration * 1000); |
461 |
if (splId != null && !splId.isEmpty()) { |
462 |
ligerIntent.putExtra(MainActivity.INTENT_KEY_STORYPATH_LIBRARY_ID, splId); |
463 |
} else if (splPath != null && !splPath.isEmpty()) { |
464 |
ligerIntent.putExtra(MainActivity.INTENT_KEY_STORYPATH_LIBRARY_PATH, splPath); |
465 |
} else if (instancePath != null && !instancePath.isEmpty()) { |
466 |
ligerIntent.putExtra(MainActivity.INTENT_KEY_STORYPATH_INSTANCE_PATH, instancePath); |
467 |
} |
468 |
context.startActivity(ligerIntent); |
469 |
} |
470 |
|
471 |
protected class IndexTask extends AsyncTask<Void, Void, Boolean> { |
472 |
|
473 |
// TODO: ADJUST THIS TO ACCOUNT FOR STORING AVAILABLE INDEX IN DB
|
474 |
|
475 |
private Context mContext; |
476 |
private boolean forceDownload; |
477 |
|
478 |
public IndexTask(Context context, boolean forceDownload) { |
479 |
this.mContext = context;
|
480 |
this.forceDownload = forceDownload;
|
481 |
} |
482 |
|
483 |
@Override
|
484 |
protected Boolean doInBackground(Void... params) { |
485 |
|
486 |
Timber.d("IndexTask.doInBackground IS RUNNING");
|
487 |
|
488 |
boolean loginRequest = false; |
489 |
|
490 |
ServerManager sm = StoryMakerApp.getServerManager(); |
491 |
|
492 |
if (mCacheWordHandler.isLocked()) {
|
493 |
|
494 |
// prevent credential check attempt if database is locked
|
495 |
Timber.d("cacheword locked, skipping index credential check");
|
496 |
// user is not logged in, update status flag if necessary
|
497 |
if (loggedIn) {
|
498 |
loggedIn = false;
|
499 |
} |
500 |
|
501 |
} else if (sm.hasCreds()) { |
502 |
// user is logged in, update status flag if necessary
|
503 |
if (!loggedIn) {
|
504 |
loggedIn = true;
|
505 |
loginRequest = true; // user just logged in, need to check server |
506 |
} |
507 |
} else {
|
508 |
// user is not logged in, update status flag if necessary
|
509 |
if (loggedIn) {
|
510 |
loggedIn = false;
|
511 |
} |
512 |
} |
513 |
|
514 |
// check server if user just logged in
|
515 |
if (loginRequest) {
|
516 |
Timber.d("USER LOGGED IN, CHECK SERVER");
|
517 |
|
518 |
// reset available index
|
519 |
StorymakerIndexManager.copyAvailableIndex(mContext, false);
|
520 |
|
521 |
// attempt to download new assignments
|
522 |
return Boolean.valueOf(sm.index()); |
523 |
} |
524 |
|
525 |
// check server if user insists (if database is unlocked)
|
526 |
if (forceDownload && !mCacheWordHandler.isLocked()) {
|
527 |
Timber.d("UPDATE REQUIRED, CHECK SERVER");
|
528 |
|
529 |
// reset available index
|
530 |
StorymakerIndexManager.copyAvailableIndex(mContext, false);
|
531 |
|
532 |
// attempt to download new assignments
|
533 |
return Boolean.valueOf(sm.index()); |
534 |
} |
535 |
|
536 |
// no-op
|
537 |
return false; |
538 |
} |
539 |
|
540 |
protected void onPostExecute(Boolean result) { |
541 |
if (result.booleanValue()) {
|
542 |
Timber.d("DOWNLOADED ASSIGNMENTS AND UPDATED AVAILABLE INDEX");
|
543 |
} else {
|
544 |
Timber.d("DID NOT DOWNLOAD ASSIGNMENTS OR UPDATE AVAILABLE INDEX");
|
545 |
} |
546 |
|
547 |
//RES
|
548 |
//mSwipeRefreshLayout.setRefreshing(false);
|
549 |
|
550 |
// resolve available/installed conflicts and grab updates if needed
|
551 |
if (!StorymakerDownloadHelper.checkAndDownload(mContext, availableIndexItemDao, installedIndexItemDao, queueItemDao)) {
|
552 |
Toast.makeText(mContext, getString(R.string.home_downloading_content), Toast.LENGTH_LONG).show(); |
553 |
} |
554 |
// refresh regardless (called from onResume and OnRefreshListener)
|
555 |
initActivityList(); |
556 |
} |
557 |
} |
558 |
|
559 |
@Override
|
560 |
public void onSaveInstanceState(Bundle outState) { |
561 |
super.onSaveInstanceState(outState);
|
562 |
} |
563 |
|
564 |
//if the user hasn't registered with the user, show the login screen
|
565 |
private void checkCreds() { |
566 |
|
567 |
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); |
568 |
|
569 |
String user = settings.getString("user", null); |
570 |
|
571 |
if (user == null) { |
572 |
Intent intent = new Intent(this, LoginActivity.class); |
573 |
startActivity(intent); |
574 |
} |
575 |
} |
576 |
|
577 |
@Override
|
578 |
public boolean onCreateOptionsMenu(Menu menu) { |
579 |
getMenuInflater().inflate(R.menu.activity_home, menu); |
580 |
return true; |
581 |
} |
582 |
|
583 |
|
584 |
public void launchNewProject() { |
585 |
// need to check this to determine whether there is a storage issue that will cause a crash
|
586 |
File actualStorageDirectory = StorageHelper.getActualStorageDirectory(this); |
587 |
|
588 |
if (actualStorageDirectory != null) { |
589 |
launchLiger(this, "default_library", null, null); |
590 |
} else {
|
591 |
//show storage error message
|
592 |
new AlertDialog.Builder(this) |
593 |
.setTitle(Utils.getAppName(this))
|
594 |
.setIcon(android.R.drawable.ic_dialog_info) |
595 |
.setMessage(R.string.err_storage_not_available) |
596 |
.show(); |
597 |
} |
598 |
} |
599 |
|
600 |
@Override
|
601 |
public boolean onOptionsItemSelected(MenuItem item) { |
602 |
|
603 |
if (item.getItemId() == android.R.id.home) {
|
604 |
toggleDrawer(); |
605 |
return true; |
606 |
// } else if (item.getItemId() == R.id.menu_new_project) {
|
607 |
// // need to check this to determine whether there is a storage issue that will cause a crash
|
608 |
// File actualStorageDirectory = StorageHelper.getActualStorageDirectory(this);
|
609 |
//
|
610 |
// if (actualStorageDirectory != null) {
|
611 |
// launchNewProject();
|
612 |
// } else {
|
613 |
// //show storage error message
|
614 |
// new AlertDialog.Builder(this)
|
615 |
// .setTitle(Utils.getAppName(this))
|
616 |
// .setIcon(android.R.drawable.ic_dialog_info)
|
617 |
// .setMessage(R.string.err_storage_not_available)
|
618 |
// .show();
|
619 |
// }
|
620 |
//
|
621 |
// return true;
|
622 |
} else if (item.getItemId() == R.id.menu_about) { |
623 |
String url = "https://storymaker.org"; |
624 |
|
625 |
Intent i = new Intent(Intent.ACTION_VIEW);
|
626 |
i.setData(Uri.parse(url)); |
627 |
startActivity(i); |
628 |
return true; |
629 |
} else if (item.getItemId() == R.id.menu_hide) { |
630 |
hideLauncherIcon(); |
631 |
} |
632 |
|
633 |
return super.onOptionsItemSelected(item); |
634 |
} |
635 |
|
636 |
protected abstract void initActivityList(); |
637 |
|
638 |
protected void checkForUpdates() { |
639 |
if (BuildConfig.DEBUG) {
|
640 |
UpdateManager.register(this, AppConstants.HOCKEY_APP_ID);
|
641 |
} |
642 |
} |
643 |
|
644 |
protected void checkForTor() { |
645 |
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); |
646 |
|
647 |
boolean useTor = settings.getBoolean("pusetor", false); |
648 |
|
649 |
if (useTor) {
|
650 |
|
651 |
if (!OrbotHelper.isOrbotInstalled(this)) { |
652 |
startActivity(OrbotHelper.getOrbotInstallIntent(this));
|
653 |
} else if (!OrbotHelper.isOrbotRunning(this)) { |
654 |
OrbotHelper.requestStartTor(this);
|
655 |
} |
656 |
} |
657 |
} |
658 |
|
659 |
protected static final ComponentName LAUNCHER_COMPONENT_NAME = new ComponentName( |
660 |
"org.storymaker.app", "org.storymaker.app.Launcher"); |
661 |
|
662 |
protected void hideLauncherIcon() { |
663 |
|
664 |
AlertDialog.Builder builder = new AlertDialog.Builder(this); |
665 |
builder.setTitle("Important!");
|
666 |
builder.setMessage("This will hide the app's icon in the launcher.\n\nTo show the app again, dial phone number 98765.");
|
667 |
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
668 |
public void onClick(DialogInterface dialog, int which) { |
669 |
|
670 |
getPackageManager().setComponentEnabledSetting(LAUNCHER_COMPONENT_NAME, |
671 |
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, |
672 |
PackageManager.DONT_KILL_APP); |
673 |
|
674 |
finish(); |
675 |
} |
676 |
}); |
677 |
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
678 |
public void onClick(DialogInterface dialog, int which) { |
679 |
|
680 |
|
681 |
} |
682 |
}); |
683 |
builder.setCancelable(true);
|
684 |
builder.setIcon(android.R.drawable.ic_dialog_alert); |
685 |
builder.show(); |
686 |
} |
687 |
|
688 |
protected void showLauncherIcon() { |
689 |
getPackageManager().setComponentEnabledSetting(LAUNCHER_COMPONENT_NAME, |
690 |
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, |
691 |
PackageManager.DONT_KILL_APP); |
692 |
} |
693 |
|
694 |
protected boolean isLauncherIconVisible() { |
695 |
int enabledSetting = getPackageManager()
|
696 |
.getComponentEnabledSetting(LAUNCHER_COMPONENT_NAME); |
697 |
return enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
698 |
} |
699 |
|
700 |
protected void checkForCrashes() { |
701 |
//CrashManager.register(this, AppConstants.HOCKEY_APP_ID);
|
702 |
CrashManager.register(this, AppConstants.HOCKEY_APP_ID, new CrashManagerListener() { |
703 |
public String getDescription() { |
704 |
String description = ""; |
705 |
|
706 |
try {
|
707 |
//Process process = Runtime.getRuntime().exec("logcat -d HockeyApp:D *:S");
|
708 |
Process process = Runtime.getRuntime().exec("logcat -d"); |
709 |
BufferedReader bufferedReader =
|
710 |
new BufferedReader(new InputStreamReader(process.getInputStream())); |
711 |
|
712 |
StringBuilder log = new StringBuilder(); |
713 |
String line;
|
714 |
while ((line = bufferedReader.readLine()) != null) { |
715 |
log.append(line); |
716 |
log.append(System.getProperty("line.separator")); |
717 |
} |
718 |
bufferedReader.close(); |
719 |
|
720 |
description = log.toString(); |
721 |
} catch (IOException e) { |
722 |
} |
723 |
|
724 |
return description;
|
725 |
} |
726 |
}); |
727 |
} |
728 |
|
729 |
protected void showPreferences () |
730 |
{ |
731 |
Intent intent = new Intent(this,SimplePreferences.class); |
732 |
this.startActivityForResult(intent, 9999); |
733 |
} |
734 |
|
735 |
public class PauseListener implements DialogInterface.OnClickListener { |
736 |
|
737 |
private scal.io.liger.model.sqlbrite.ExpansionIndexItem eItem;
|
738 |
|
739 |
public PauseListener(scal.io.liger.model.sqlbrite.ExpansionIndexItem eItem) {
|
740 |
super();
|
741 |
|
742 |
this.eItem = eItem;
|
743 |
} |
744 |
|
745 |
@Override
|
746 |
public void onClick(DialogInterface dialog, int which) { |
747 |
|
748 |
Timber.d("PAUSE...");
|
749 |
|
750 |
// stop associated threads
|
751 |
|
752 |
ArrayList<Thread> currentThreads = downloadThreads.get(eItem.getExpansionId()); |
753 |
|
754 |
if (currentThreads != null) { |
755 |
for (Thread thread : currentThreads) { |
756 |
Timber.d("STOPPING THREAD " + thread.getId());
|
757 |
thread.interrupt(); |
758 |
} |
759 |
} |
760 |
|
761 |
downloadThreads.remove(eItem.getExpansionId()); |
762 |
|
763 |
} |
764 |
} |
765 |
|
766 |
@Override
|
767 |
public void onResume() { |
768 |
super.onResume();
|
769 |
|
770 |
getActionBar().setTitle(Utils.getAppName(this));
|
771 |
|
772 |
checkForCrashes(); |
773 |
|
774 |
//if (!DownloadHelper.checkAllFiles(this) && downloadPoller == null) {
|
775 |
// integrate with index task
|
776 |
//if (!DownloadHelper.checkAndDownload(this)) {
|
777 |
// don't poll, just pop up message if a download was initiated
|
778 |
//downloadPoller = new DownloadPoller();
|
779 |
//downloadPoller.execute("foo");
|
780 |
// Toast.makeText(this, "Downloading content and/or updating installed files", Toast.LENGTH_LONG).show(); // FIXME move to strings.xml
|
781 |
//} //else {
|
782 |
// merge this with index task
|
783 |
// initActivityList();
|
784 |
|
785 |
// need to check this to determine whether there is a storage issue that will cause a crash
|
786 |
File actualStorageDirectory = StorageHelper.getActualStorageDirectory(this); |
787 |
|
788 |
if (actualStorageDirectory != null) { |
789 |
IndexTask iTask = new IndexTask(this, false); // don't force download on resume (currently triggers only on login) |
790 |
iTask.execute(); |
791 |
} else {
|
792 |
//show storage error message
|
793 |
new AlertDialog.Builder(this) |
794 |
.setTitle(Utils.getAppName(this))
|
795 |
.setIcon(android.R.drawable.ic_dialog_info) |
796 |
.setMessage(R.string.err_storage_not_available) |
797 |
.show(); |
798 |
} |
799 |
|
800 |
//}
|
801 |
|
802 |
boolean isExternalStorageReady = Utils.Files.isExternalStorageReady();
|
803 |
|
804 |
if (!isExternalStorageReady) {
|
805 |
//show storage error message
|
806 |
new AlertDialog.Builder(this) |
807 |
.setTitle(Utils.getAppName(this))
|
808 |
.setIcon(android.R.drawable.ic_dialog_info) |
809 |
.setMessage(R.string.err_storage_not_ready) |
810 |
.show(); |
811 |
|
812 |
} |
813 |
|
814 |
if (getIntent() != null && getIntent().hasExtra("showlauncher")) { |
815 |
if (getIntent().getBooleanExtra("showlauncher", false)) { |
816 |
showLauncherIcon(); |
817 |
} |
818 |
} |
819 |
|
820 |
checkAndEnforcePermissions(); // FIXME we should handle these at time of use instead of like this
|
821 |
} |
822 |
|
823 |
protected void showSPLSelectorPopup(final String[] names, final String[] paths) { |
824 |
AlertDialog.Builder builder = new AlertDialog.Builder(this); |
825 |
|
826 |
builder.setTitle("Choose Story File(SdCard/Liger/)").setItems(names, new DialogInterface.OnClickListener() { |
827 |
public void onClick(DialogInterface dialog, int index) { |
828 |
launchLiger(BaseHomeActivity.this, null, null, paths[index]); |
829 |
} |
830 |
}); |
831 |
|
832 |
AlertDialog alert = builder.create(); |
833 |
alert.show(); |
834 |
} |
835 |
|
836 |
// HAD TO SPLIT OUT INTO A METHOD
|
837 |
public void handleClick(ExpansionIndexItem eItem, HashMap<String, ExpansionIndexItem> installedIds, boolean showDialog) { |
838 |
|
839 |
// initiate check/download whether installed or not
|
840 |
HashMap<String, Thread> newThreads = StorymakerDownloadHelper.checkAndDownload(BaseHomeActivity.this, eItem, installedIndexItemDao, queueItemDao, true); // <- THIS SHOULD PICK UP EXISTING PARTIAL FILES |
841 |
// <- THIS ALSO NEEDS TO NOT INTERACT WITH THE INDEX
|
842 |
// <- METADATA UPDATE SHOULD HAPPEN WHEN APP IS INITIALIZED
|
843 |
|
844 |
// if any download threads were initiated, item is not ready to open
|
845 |
|
846 |
boolean readyToOpen = true; |
847 |
|
848 |
if (newThreads.size() > 0) { |
849 |
readyToOpen = false;
|
850 |
|
851 |
// update stored threads for index item
|
852 |
|
853 |
ArrayList<Thread> currentThreads = downloadThreads.get(eItem.getExpansionId()); |
854 |
|
855 |
if (currentThreads == null) { |
856 |
currentThreads = new ArrayList<Thread>(); |
857 |
} |
858 |
|
859 |
for (Thread thread : newThreads.values()) { |
860 |
currentThreads.add(thread); |
861 |
} |
862 |
|
863 |
downloadThreads.put(eItem.getExpansionId(), currentThreads); |
864 |
} |
865 |
|
866 |
if (!installedIds.containsKey(eItem.getExpansionId())) {
|
867 |
|
868 |
// if clicked item is not installed, update index
|
869 |
// un-installed AvailableIndexItems need to be converted to InstalledIndexItems
|
870 |
InstalledIndexItem iItem = new InstalledIndexItem(eItem);
|
871 |
|
872 |
java.util.Date thisDate = new java.util.Date(); // FIXME we need to move this somewhere in the liger library that handles opening storypaths because this won't be triggered if we open open an instance by means other than a direct click |
873 |
iItem.setCreationDate(thisDate); |
874 |
iItem.setLastModifiedDate(thisDate); |
875 |
iItem.setCreationDate(thisDate); |
876 |
|
877 |
StorymakerIndexManager.installedIndexAdd(BaseHomeActivity.this, iItem, installedIndexItemDao); |
878 |
|
879 |
Timber.d(eItem.getExpansionId() + " NOT INSTALLED, ADDING ITEM TO INDEX");
|
880 |
|
881 |
// wait for index serialization
|
882 |
try {
|
883 |
synchronized (this) { |
884 |
wait(1000); // FIXME holy race conditions, batman |
885 |
} |
886 |
} catch (InterruptedException e) { |
887 |
// nop
|
888 |
} |
889 |
} else {
|
890 |
|
891 |
Timber.d(eItem.getExpansionId() + " INSTALLED, CHECKING FILE");
|
892 |
|
893 |
// if clicked item is installed, check state
|
894 |
if (readyToOpen) {
|
895 |
|
896 |
// clear saved threads
|
897 |
if (downloadThreads.get(eItem.getExpansionId()) != null) { |
898 |
downloadThreads.remove(eItem.getExpansionId()); |
899 |
} |
900 |
|
901 |
// update db record with flag
|
902 |
if (!eItem.isInstalled()) {
|
903 |
Timber.d("SET INSTALLED FLAG FOR " + eItem.getExpansionId());
|
904 |
eItem.setInstalledFlag(true);
|
905 |
InstalledIndexItem iItem = new InstalledIndexItem(eItem);
|
906 |
StorymakerIndexManager.installedIndexAdd(this, iItem, installedIndexItemDao);
|
907 |
} |
908 |
|
909 |
// if file has been downloaded, open file
|
910 |
Timber.d(eItem.getExpansionId() + " INSTALLED, FILE OK");
|
911 |
|
912 |
// update with new thumbnail path
|
913 |
// move this somewhere that it can be triggered by completed download?
|
914 |
ContentPackMetadata metadata = scal.io.liger.IndexManager.loadContentMetadata(BaseHomeActivity.this, |
915 |
eItem.getPackageName(), |
916 |
eItem.getExpansionId(), |
917 |
StoryMakerApp.getCurrentLocale().getLanguage()); |
918 |
|
919 |
if (metadata == null) { |
920 |
Toast.makeText(BaseHomeActivity.this, getString(R.string.home_metadata_missing), Toast.LENGTH_LONG).show(); |
921 |
Timber.e("failed to load content metadata");
|
922 |
} else if ((eItem.getThumbnailPath() == null) || (!eItem.getThumbnailPath().equals(metadata.getContentPackThumbnailPath()))) { // FIXME use StringUtils |
923 |
|
924 |
Timber.d(eItem.getExpansionId() + " FIRST OPEN, UPDATING THUMBNAIL PATH");
|
925 |
|
926 |
eItem.setThumbnailPath(metadata.getContentPackThumbnailPath()); |
927 |
|
928 |
// un-installed AvailableIndexItems need to be converted to InstalledIndexItems
|
929 |
InstalledIndexItem iItem = new InstalledIndexItem(eItem);
|
930 |
StorymakerIndexManager.installedIndexAdd(BaseHomeActivity.this, iItem, installedIndexItemDao); |
931 |
|
932 |
// wait for index serialization
|
933 |
try {
|
934 |
synchronized (this) { |
935 |
wait(1000); // FIXME holy race conditions, batman |
936 |
} |
937 |
} catch (InterruptedException e) { |
938 |
// nop
|
939 |
} |
940 |
} |
941 |
|
942 |
ArrayList<scal.io.liger.model.InstanceIndexItem> contentIndex = scal.io.liger.IndexManager.loadContentIndexAsList(BaseHomeActivity.this,
|
943 |
eItem.getPackageName(), |
944 |
eItem.getExpansionId(), |
945 |
StoryMakerApp.getCurrentLocale().getLanguage()); |
946 |
|
947 |
if ((contentIndex == null) || (contentIndex.size() < 1)) { |
948 |
Toast.makeText(BaseHomeActivity.this, getString(R.string.home_index_missing), Toast.LENGTH_LONG).show(); |
949 |
Timber.e("failed to load content index");
|
950 |
} else if (contentIndex.size() == 1) { |
951 |
launchLiger(BaseHomeActivity.this, null, null, contentIndex.get(0).getInstanceFilePath()); |
952 |
} else {
|
953 |
String[] names = new String[contentIndex.size()]; |
954 |
String[] paths = new String[contentIndex.size()]; |
955 |
int i = 0; |
956 |
for (scal.io.liger.model.InstanceIndexItem item : contentIndex) {
|
957 |
names[i] = item.getTitle(); |
958 |
paths[i] = item.getInstanceFilePath(); |
959 |
i++; |
960 |
} |
961 |
showSPLSelectorPopup(names, paths); |
962 |
} |
963 |
} else {
|
964 |
// if file is being downloaded, don't open
|
965 |
Timber.d(eItem.getExpansionId() + " INSTALLED, CURRENTLY DOWNLOADING FILE");
|
966 |
|
967 |
// if necessary, un-flag db record (this probably indicates an installed file that is being patched
|
968 |
if (eItem.isInstalled()) {
|
969 |
Timber.d("UN-SET INSTALLED FLAG FOR " + eItem.getExpansionId());
|
970 |
eItem.setInstalledFlag(false);
|
971 |
InstalledIndexItem iItem = new InstalledIndexItem(eItem);
|
972 |
StorymakerIndexManager.installedIndexAdd(this, iItem, installedIndexItemDao);
|
973 |
} |
974 |
|
975 |
// create pause/cancel dialog
|
976 |
|
977 |
if (showDialog) {
|
978 |
new AlertDialog.Builder(BaseHomeActivity.this)
|
979 |
.setTitle(R.string.stop_download) |
980 |
.setMessage(eItem.getTitle()) |
981 |
.setNegativeButton(getString(R.string.cancel), null)
|
982 |
.setNeutralButton(getString(R.string.pause), new PauseListener(eItem))
|
983 |
.setPositiveButton(getString(R.string.stop), new CancelListener(eItem))
|
984 |
.show(); |
985 |
} |
986 |
|
987 |
// Toast.makeText(HomeActivity.this, "Please wait for this content pack to finish downloading", Toast.LENGTH_LONG).show(); // FIXME move to strings.xml
|
988 |
} |
989 |
} |
990 |
|
991 |
|
992 |
} |
993 |
|
994 |
|
995 |
public class CancelListener implements DialogInterface.OnClickListener { |
996 |
|
997 |
private ExpansionIndexItem eItem;
|
998 |
|
999 |
public CancelListener(ExpansionIndexItem eItem) {
|
1000 |
super();
|
1001 |
|
1002 |
this.eItem = eItem;
|
1003 |
} |
1004 |
|
1005 |
@Override
|
1006 |
public void onClick(DialogInterface dialog, int which) { |
1007 |
|
1008 |
Timber.d("CANCEL...");
|
1009 |
// remove from installed index
|
1010 |
|
1011 |
// un-installed AvailableIndexItems need to be converted to InstalledIndexItems
|
1012 |
InstalledIndexItem iItem = new InstalledIndexItem(eItem);
|
1013 |
StorymakerIndexManager.installedIndexRemove(BaseHomeActivity.this, iItem, installedIndexItemDao); |
1014 |
|
1015 |
// stop associated threads and delete associated files
|
1016 |
|
1017 |
ArrayList<Thread> currentThreads = downloadThreads.get(eItem.getExpansionId()); |
1018 |
|
1019 |
if (currentThreads != null) { |
1020 |
for (Thread thread : currentThreads) { |
1021 |
Timber.d("STOPPING THREAD " + thread.getId());
|
1022 |
thread.interrupt(); |
1023 |
} |
1024 |
} |
1025 |
|
1026 |
downloadThreads.remove(eItem.getExpansionId()); |
1027 |
|
1028 |
Timber.d("DELETE STUFF?");
|
1029 |
|
1030 |
File fileDirectory = StorageHelper.getActualStorageDirectory(BaseHomeActivity.this);
|
1031 |
WildcardFileFilter fileFilter = new WildcardFileFilter(eItem.getExpansionId() + ".*"); |
1032 |
for (File foundFile : FileUtils.listFiles(fileDirectory, fileFilter, null)) { |
1033 |
Timber.d("STOPPED THREAD: FOUND " + foundFile.getPath() + ", DELETING"); |
1034 |
FileUtils.deleteQuietly(foundFile); |
1035 |
} |
1036 |
} |
1037 |
} |
1038 |
|
1039 |
public void updateInstanceIndexItemLastOpenedDate(InstanceIndexItem item) { |
1040 |
java.util.Date thisDate = new java.util.Date();
|
1041 |
//Log.d("BaseHomeActivity", "setLastOpenedDate " + thisDate.toString());
|
1042 |
instanceIndexItemDao.updateInstanceItemLastOpenedDate(item, thisDate); |
1043 |
} |
1044 |
|
1045 |
//this method loops through a HashMap of ExpansionIndexItems
|
1046 |
// and returns the ones that have a certain content type i.e. "guide", "lesson", "template"
|
1047 |
// used to filter an existing query set rather than running extra queries with getAvailableIndexItemsByType() or getInstalledIndexItemsByType()
|
1048 |
public static ArrayList<String> getIndexItemIdsByType(HashMap<String, ExpansionIndexItem> installedIds, String type) { |
1049 |
|
1050 |
ArrayList<String> indexItemIds = new ArrayList<String>(); |
1051 |
|
1052 |
for (String key : installedIds.keySet()) { |
1053 |
|
1054 |
ExpansionIndexItem item = installedIds.get(key); |
1055 |
|
1056 |
if (StringUtils.equals(item.getContentType(),type)) {
|
1057 |
indexItemIds.add(key); |
1058 |
} |
1059 |
|
1060 |
} |
1061 |
|
1062 |
return indexItemIds;
|
1063 |
|
1064 |
} |
1065 |
|
1066 |
|
1067 |
} |