diff options
Diffstat (limited to 'android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenDeviceIconManager.java')
-rw-r--r-- | android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenDeviceIconManager.java | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenDeviceIconManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenDeviceIconManager.java new file mode 100644 index 000000000..b2b8e6b14 --- /dev/null +++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenDeviceIconManager.java @@ -0,0 +1,214 @@ +package com.smartdevicelink.managers.lockscreen; + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.smartdevicelink.util.AndroidTools; +import com.smartdevicelink.util.DebugTool; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * <strong>LockScreenDeviceIconManager</strong> <br> + * + * The LockScreenDeviceIconManager handles the logic of caching and retrieving cached lock screen icons <br> + * + */ +class LockScreenDeviceIconManager { + + private Context context; + private static final String SDL_DEVICE_STATUS_SHARED_PREFS = "sdl.lockScreenIcon"; + private static final String STORED_ICON_DIRECTORY_PATH = "sdl/lock_screen_icon/"; + + interface OnIconRetrievedListener { + void onImageRetrieved(Bitmap icon); + void onError(String info); + } + + LockScreenDeviceIconManager(Context context) { + this.context = context; + File lockScreenDirectory = new File(context.getCacheDir(), STORED_ICON_DIRECTORY_PATH); + lockScreenDirectory.mkdirs(); + } + + /** + * Will try to return a lock screen icon either from cache or downloaded + * if it fails iconRetrievedListener.OnError will be called with corresponding error message + * @param iconURL url that the lock screen icon is downloaded from + * @param iconRetrievedListener an interface that will implement onIconReceived and OnError methods + */ + void retrieveIcon(String iconURL, OnIconRetrievedListener iconRetrievedListener) { + Bitmap icon = null; + try { + if (isIconCachedAndValid(iconURL)) { + DebugTool.logInfo("Icon Is Up To Date"); + icon = getFileFromCache(iconURL); + if (icon == null) { + DebugTool.logInfo("Icon from cache was null, attempting to re-download"); + icon = AndroidTools.downloadImage(iconURL); + if (icon != null) { + saveFileToCache(icon, iconURL); + } else { + iconRetrievedListener.onError("Icon downloaded was null"); + return; + } + } + iconRetrievedListener.onImageRetrieved(icon); + } else { + // The icon is unknown or expired. Download the image, save it to the cache, and update the archive file + DebugTool.logInfo("Lock Screen Icon Update Needed"); + icon = AndroidTools.downloadImage(iconURL); + if (icon != null) { + saveFileToCache(icon, iconURL); + iconRetrievedListener.onImageRetrieved(icon); + } else { + iconRetrievedListener.onError("Icon downloaded was null"); + } + } + } catch (IOException e) { + iconRetrievedListener.onError("device Icon Error Downloading, Will attempt to grab cached Icon even if expired: \n" + e.toString()); + icon = getFileFromCache(iconURL); + if (icon != null) { + iconRetrievedListener.onImageRetrieved(icon); + } else { + iconRetrievedListener.onError("Unable to retrieve icon from cache"); + } + } + } + + /** + * Will decide if a cached icon is available and up to date + * @param iconUrl url will be hashed and used to look up last updated timestamp in shared preferences + * @return True when icon details are in shared preferences and less than 30 days old, False if icon details are too old or not found + */ + private boolean isIconCachedAndValid(String iconUrl) { + String iconHash = getMD5HashFromIconUrl(iconUrl); + SharedPreferences sharedPref = this.context.getSharedPreferences(SDL_DEVICE_STATUS_SHARED_PREFS, Context.MODE_PRIVATE); + String iconLastUpdatedTime = sharedPref.getString(iconHash, null); + if(iconLastUpdatedTime == null) { + DebugTool.logInfo("No Icon Details Found In Shared Preferences"); + return false; + } else { + DebugTool.logInfo("Icon Details Found"); + long lastUpdatedTime = 0; + try { + lastUpdatedTime = Long.parseLong(iconLastUpdatedTime); + } catch (NumberFormatException e) { + DebugTool.logInfo("Invalid time stamp stored to shared preferences, clearing cache and share preferences"); + clearIconDirectory(); + sharedPref.edit().clear().commit(); + } + long currentTime = System.currentTimeMillis(); + + long timeDifference = currentTime - lastUpdatedTime; + long daysBetweenLastUpdate = timeDifference / (1000 * 60 * 60 * 24); + return daysBetweenLastUpdate < 30; + } + } + + /** + * Will try to save icon to cache + * @param icon the icon bitmap that should be saved to cache + * @param iconUrl the url where the icon was retrieved will be hashed and used for file and file details lookup + */ + private void saveFileToCache(Bitmap icon, String iconUrl) { + String iconHash = getMD5HashFromIconUrl(iconUrl); + File f = new File(this.context.getCacheDir() + "/" + STORED_ICON_DIRECTORY_PATH, iconHash); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + icon.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos); + byte[] bitmapData = bos.toByteArray(); + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(f); + fos.write(bitmapData); + fos.flush(); + fos.close(); + writeDeviceIconParametersToSharedPreferences(iconHash); + } catch (Exception e) { + DebugTool.logError("Failed to save icon to cache"); + e.printStackTrace(); + } + } + + /** + * Will try to retrieve icon bitmap from cached directory + * @param iconUrl the url where the icon was retrieved will be hashed and used to look up file location + * @return bitmap of device icon or null if it fails to find the icon or read from shared preferences + */ + private Bitmap getFileFromCache(String iconUrl) { + String iconHash = getMD5HashFromIconUrl(iconUrl); + SharedPreferences sharedPref = this.context.getSharedPreferences(SDL_DEVICE_STATUS_SHARED_PREFS, Context.MODE_PRIVATE); + String iconLastUpdatedTime = sharedPref.getString(iconHash, null); + + if (iconLastUpdatedTime != null) { + Bitmap cachedIcon = BitmapFactory.decodeFile(this.context.getCacheDir() + "/" + STORED_ICON_DIRECTORY_PATH + "/" + iconHash); + if(cachedIcon == null) { + DebugTool.logError("Failed to get Bitmap from decoding file cache"); + clearIconDirectory(); + sharedPref.edit().clear().commit(); + return null; + } else { + return cachedIcon; + } + } else { + DebugTool.logError("Failed to get shared preferences"); + return null; + } + } + + /** + * Will write information about the icon to shared preferences + * icon information will have a look up key of the hashed icon url and the current timestamp to indicated when the icon was last updated. + * @param iconHash the url where the icon was retrieved will be hashed and used lookup key + */ + private void writeDeviceIconParametersToSharedPreferences(String iconHash) { + SharedPreferences sharedPref = this.context.getSharedPreferences(SDL_DEVICE_STATUS_SHARED_PREFS, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString(iconHash, String.valueOf(System.currentTimeMillis())); + editor.commit(); + } + + /** + * Create an MD5 hash of the icon url for file storage and lookup/shared preferences look up + * @param iconUrl the url where the icon was retrieved + * @return MD5 hash of the icon URL + */ + private String getMD5HashFromIconUrl(String iconUrl) { + String iconHash = null; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest(iconUrl.getBytes()); + BigInteger no = new BigInteger(1, messageDigest); + String hashtext = no.toString(16); + while (hashtext.length() < 32) { + hashtext = "0" + hashtext; + } + iconHash = hashtext; + } catch (NoSuchAlgorithmException e) { + DebugTool.logError("Unable to hash icon url"); + e.printStackTrace(); + } + return iconHash; + } + + /** + * Clears all files in the directory where lock screen icons are cached + */ + private void clearIconDirectory() { + File iconDir = new File(context.getCacheDir() + "/" + STORED_ICON_DIRECTORY_PATH); + if (iconDir.listFiles() != null) { + for (File child : iconDir.listFiles()) { + child.delete(); + } + } + } +} |