This shows you the differences between two versions of the page.
smd:laboratoare:06 [2021/04/21 20:13] adriana.draghici [Resources & Useful Links] |
smd:laboratoare:06 [2021/05/20 21:30] (current) adriana.draghici [Shared preferences] |
||
---|---|---|---|
Line 20: | Line 20: | ||
<note important>Android API Level 29 introduced important changes to how storage is accessed, driven by the need for increased privacy. | <note important>Android API Level 29 introduced important changes to how storage is accessed, driven by the need for increased privacy. | ||
- | It provided Scoped Storage([[https://developer.android.com/training/data-storage#scoped-storage|documentation]][[https://www.raywenderlich.com/9577211-scoped-storage-in-android-10-getting-started|tutorial]]). Api Level 30 also introduced some updates related to storage, check [[https://developer.android.com/about/versions/11/privacy/storage|this link]] for some information about them. </note> | + | It provided **Scoped Storage** ([[https://developer.android.com/training/data-storage#scoped-storage|documentation]], [[https://www.raywenderlich.com/9577211-scoped-storage-in-android-10-getting-started|tutorial]]). Api Level 30 also introduced some updates related to storage, check [[https://developer.android.com/about/versions/11/privacy/storage|this link]] for some information about them. </note> |
====Internal Storage==== | ====Internal Storage==== | ||
Line 49: | Line 49: | ||
* accessing public external files requires the permissions | * accessing public external files requires the permissions | ||
* accessing private external files does not require the permissions from API Level 18 (Android 4.4 - KitKat). | * accessing private external files does not require the permissions from API Level 18 (Android 4.4 - KitKat). | ||
- | * **__Security tips:__** | + | <note important>**__Security tips:__** |
* validate the data read from external storage | * validate the data read from external storage | ||
* encrypt sensitive data stored in external storage | * encrypt sensitive data stored in external storage | ||
* decide whether the data should be persisted after the app is installed or not. | * decide whether the data should be persisted after the app is installed or not. | ||
* ask for the permissions at runtime, preferably showing a custom message informing the user why do you need those permissions. | * ask for the permissions at runtime, preferably showing a custom message informing the user why do you need those permissions. | ||
+ | </note> | ||
**How-to:** | **How-to:** | ||
* Declare the permissions in the manifest (if needed) | * Declare the permissions in the manifest (if needed) | ||
Line 93: | Line 93: | ||
sharedPref = this.getSharedPreferences("mysettings", Context.MODE_PRIVATE); | sharedPref = this.getSharedPreferences("mysettings", Context.MODE_PRIVATE); | ||
// or | // or | ||
- | sharedPref = PreferenceManager.getDefaultSharedPreferences(context); | + | sharedPref = PreferenceManager.getDefaultSharedPreferences(context); //!!! recently deprecated in API level 29 |
</code> | </code> | ||
Line 129: | Line 129: | ||
==== Task 0 - Init ==== | ==== Task 0 - Init ==== | ||
- | Create a new Android application project. Download the lab archive and use its content, or start with your own UI design. | + | Create a new Android application project. You can download the lab archive and use its layout, or start with your own UI design. |
==== Task 1 - Runtime permission check ==== | ==== Task 1 - Runtime permission check ==== | ||
Line 160: | Line 160: | ||
Provide the functionality from tasks 1 and 2 using internal storage instead of external. | Provide the functionality from tasks 1 and 2 using internal storage instead of external. | ||
* You can choose to store the file using one of the methods described in the [[smd:laboratoare:06##internal_storage|Internal Storage]] section. | * You can choose to store the file using one of the methods described in the [[smd:laboratoare:06##internal_storage|Internal Storage]] section. | ||
- | * Log the path of the file, try to access it from the command line. | + | * Log the path of the file, try to access it from the command line (adb shell). |
==== Task 5 - Shared preferences ==== | ==== Task 5 - Shared preferences ==== | ||
Line 170: | Line 170: | ||
* When the user selects an item from the spinner, store it as a shared preference. Use [[https://developer.android.com/reference/android/widget/AdapterView.html#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)|setOnItemSelectedListener]]. | * When the user selects an item from the spinner, store it as a shared preference. Use [[https://developer.android.com/reference/android/widget/AdapterView.html#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)|setOnItemSelectedListener]]. | ||
* When the user clicks Download, use an external or internal path, depending on the value stored in the shared preferences. If the value is "Undefined", show a toast telling the user to choose a type of storage. | * When the user clicks Download, use an external or internal path, depending on the value stored in the shared preferences. If the value is "Undefined", show a toast telling the user to choose a type of storage. | ||
+ | |||
+ | <spoiler Example > | ||
+ | <code java> | ||
+ | private String getStorageType() { | ||
+ | SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); | ||
+ | return sharedPref.getString(getString(R.string.storage_type_key), "undefined"); | ||
+ | } | ||
+ | |||
+ | private void storeStorageType(String type) | ||
+ | SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit(); | ||
+ | editor.putString(getString(R.string.storage_type_key), type); | ||
+ | editor.apply(); | ||
+ | } | ||
+ | |||
+ | private class StorageTypeSelectedListener implements AdapterView.OnItemSelectedListener { | ||
+ | |||
+ | @Override | ||
+ | public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { | ||
+ | String selectedItem = adapterView.getItemAtPosition(i).toString(); | ||
+ | Log.d(TAG, "Selected storage type: " + selectedItem); | ||
+ | storeStorageType(selectedItem); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void onNothingSelected(AdapterView<?> adapterView) { | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | </spoiler> | ||
| | ||
Image manipulation code snippets: | Image manipulation code snippets: | ||
Line 197: | Line 226: | ||
* [[https://developer.android.com/guide/topics/data/data-storage|Android Data Storage documentation]] | * [[https://developer.android.com/guide/topics/data/data-storage|Android Data Storage documentation]] | ||
* [[https://developer.android.com/about/versions/11/privacy/storage|Storage updates in Android 11]] | * [[https://developer.android.com/about/versions/11/privacy/storage|Storage updates in Android 11]] | ||
- | * {{lab6-skel.zip|}} | + | * {{lab6_skel.zip|}} |