Simple Notepad Application for Android OS
修订版 | abf32354df425d51d5cfde0611973e0b9ddbc2aa (tree) |
---|---|
时间 | 2016-05-08 17:04:46 |
作者 | Masahiko, SAWAI <say@user...> |
Commiter | Masahiko, SAWAI |
Added runtime permission support for Android 6.0
@@ -23,24 +23,41 @@ | ||
23 | 23 | */ |
24 | 24 | package org.routine_work.notepad.prefs; |
25 | 25 | |
26 | +import android.Manifest; | |
26 | 27 | import android.app.Activity; |
27 | 28 | import android.content.Intent; |
29 | +import android.content.pm.PackageManager; | |
30 | +import android.os.Build; | |
28 | 31 | import android.os.Bundle; |
29 | -import android.util.Log; | |
30 | 32 | import android.view.View; |
31 | 33 | import android.view.View.OnClickListener; |
32 | 34 | import android.widget.Button; |
35 | +import android.widget.TextView; | |
33 | 36 | import org.routine_work.notepad.R; |
37 | +import org.routine_work.utils.Log; | |
34 | 38 | |
35 | 39 | public class BackupDatabaseActivity extends Activity |
36 | - implements OnClickListener, BackupConstants | |
37 | -{ | |
40 | + implements OnClickListener, BackupConstants { | |
38 | 41 | |
39 | 42 | private static final String LOG_TAG = "simple-notepad"; |
43 | + private final int REQUEST_EXTERNAL_STORAGE_PERMISSION = 1001; | |
40 | 44 | |
41 | 45 | @Override |
42 | - protected void onCreate(Bundle savedInstanceState) | |
43 | - { | |
46 | + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { | |
47 | + Log.v(LOG_TAG, "Hello"); | |
48 | + | |
49 | + super.onRequestPermissionsResult(requestCode, permissions, grantResults); | |
50 | + if (requestCode == REQUEST_EXTERNAL_STORAGE_PERMISSION) { | |
51 | + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |
52 | + enableBackupFunction(); | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + Log.v(LOG_TAG, "Bye"); | |
57 | + } | |
58 | + | |
59 | + @Override | |
60 | + protected void onCreate(Bundle savedInstanceState) { | |
44 | 61 | Log.v(LOG_TAG, "Hello"); |
45 | 62 | setTheme(NotepadPreferenceUtils.getTheme(this)); |
46 | 63 | super.onCreate(savedInstanceState); |
@@ -48,17 +65,38 @@ public class BackupDatabaseActivity extends Activity | ||
48 | 65 | |
49 | 66 | Button okButton = (Button) findViewById(R.id.ok_button); |
50 | 67 | okButton.setOnClickListener(this); |
68 | + okButton.setEnabled(false); | |
51 | 69 | Button cancelButton = (Button) findViewById(R.id.cancel_button); |
52 | 70 | cancelButton.setOnClickListener(this); |
71 | + | |
72 | + if (Build.VERSION.SDK_INT >= 23) { // Android 6.0 or later | |
73 | + if (PermissionUtils.hasExternalStoragePermission(this) == false) { | |
74 | + this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE_PERMISSION); | |
75 | + } | |
76 | + } | |
77 | + Log.v(LOG_TAG, "Bye"); | |
78 | + } | |
79 | + | |
80 | + @Override | |
81 | + protected void onResume() { | |
82 | + super.onResume(); | |
83 | + Log.v(LOG_TAG, "Hello"); | |
84 | + | |
85 | + if (PermissionUtils.hasExternalStoragePermission(this)) { // Android 6.0 or later | |
86 | + Log.v(LOG_TAG, "hasWriteStoragePermission() : true"); | |
87 | + enableBackupFunction(); | |
88 | + } else { | |
89 | + Log.v(LOG_TAG, "hasWriteStoragePermission() : false"); | |
90 | + disableBackupFunction(); | |
91 | + } | |
92 | + | |
53 | 93 | Log.v(LOG_TAG, "Bye"); |
54 | 94 | } |
55 | 95 | |
56 | 96 | @Override |
57 | - public void onClick(View view) | |
58 | - { | |
97 | + public void onClick(View view) { | |
59 | 98 | int id = view.getId(); |
60 | - switch (id) | |
61 | - { | |
99 | + switch (id) { | |
62 | 100 | case R.id.ok_button: |
63 | 101 | startBackupDatabaseService(); |
64 | 102 | setResult(RESULT_OK); |
@@ -71,13 +109,31 @@ public class BackupDatabaseActivity extends Activity | ||
71 | 109 | } |
72 | 110 | } |
73 | 111 | |
74 | - private void startBackupDatabaseService() | |
75 | - { | |
112 | + private void enableBackupFunction() { | |
113 | + Button okButton = (Button) findViewById(R.id.ok_button); | |
114 | + okButton.setEnabled(true); | |
115 | + | |
116 | + View rationaleView = findViewById(R.id.request_permission_rationale_external_storage_view); | |
117 | + rationaleView.setVisibility(View.GONE); | |
118 | + } | |
119 | + | |
120 | + private void disableBackupFunction() { | |
121 | + Button okButton = (Button) findViewById(R.id.ok_button); | |
122 | + okButton.setEnabled(false); | |
123 | + | |
124 | + View rationaleView = findViewById(R.id.request_permission_rationale_external_storage_view); | |
125 | + rationaleView.setVisibility(View.VISIBLE); | |
126 | + } | |
127 | + | |
128 | + private void startBackupDatabaseService() { | |
76 | 129 | Log.v(LOG_TAG, "Hello"); |
77 | 130 | |
78 | - Intent backDatabaseIntent = new Intent(this, BackupDatabaseService.class); | |
79 | - startService(backDatabaseIntent); | |
131 | + if (PermissionUtils.hasExternalStoragePermission(this)) { // re check | |
132 | + Intent backDatabaseIntent = new Intent(this, BackupDatabaseService.class); | |
133 | + startService(backDatabaseIntent); | |
134 | + } | |
80 | 135 | |
81 | 136 | Log.v(LOG_TAG, "Bye"); |
82 | 137 | } |
138 | + | |
83 | 139 | } |
@@ -0,0 +1,58 @@ | ||
1 | +/* | |
2 | + * The MIT License | |
3 | + * | |
4 | + * Copyright 2016 Masahiko, SAWAI <masahiko.sawai@gmail.com>. | |
5 | + * | |
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | + * of this software and associated documentation files (the "Software"), to deal | |
8 | + * in the Software without restriction, including without limitation the rights | |
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | + * copies of the Software, and to permit persons to whom the Software is | |
11 | + * furnished to do so, subject to the following conditions: | |
12 | + * | |
13 | + * The above copyright notice and this permission notice shall be included in | |
14 | + * all copies or substantial portions of the Software. | |
15 | + * | |
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | + * THE SOFTWARE. | |
23 | + */ | |
24 | +package org.routine_work.notepad.prefs; | |
25 | + | |
26 | +import android.Manifest; | |
27 | +import android.content.Context; | |
28 | +import android.content.pm.PackageManager; | |
29 | +import android.os.Build; | |
30 | +import org.routine_work.utils.Log; | |
31 | + | |
32 | +public class PermissionUtils { | |
33 | + | |
34 | + private static final String LOG_TAG = "simple-notepad"; | |
35 | + | |
36 | + public static boolean hasExternalStoragePermission(Context context) { | |
37 | + return hasPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE); | |
38 | + } | |
39 | + | |
40 | + public static boolean hasPermission(Context context, String permission) { | |
41 | + boolean result; | |
42 | + Log.v(LOG_TAG, "Hello"); | |
43 | + | |
44 | + if (Build.VERSION.SDK_INT >= 23) { // Android 6.0 or later | |
45 | + if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) { | |
46 | + result = true; | |
47 | + } else { | |
48 | + result = false; | |
49 | + } | |
50 | + } else { | |
51 | + result = true; | |
52 | + } | |
53 | + | |
54 | + Log.v(LOG_TAG, "Bye"); | |
55 | + return result; | |
56 | + } | |
57 | + | |
58 | +} |
@@ -23,10 +23,13 @@ | ||
23 | 23 | */ |
24 | 24 | package org.routine_work.notepad.prefs; |
25 | 25 | |
26 | +import android.Manifest; | |
26 | 27 | import android.app.Activity; |
27 | 28 | import android.app.ListActivity; |
28 | 29 | import android.content.Intent; |
30 | +import android.content.pm.PackageManager; | |
29 | 31 | import android.net.Uri; |
32 | +import android.os.Build; | |
30 | 33 | import android.os.Bundle; |
31 | 34 | import android.os.Environment; |
32 | 35 | import android.view.View; |
@@ -47,28 +50,37 @@ import org.routine_work.utils.Log; | ||
47 | 50 | * @author Masahiko, SAWAI <masahiko.sawai@gmail.com> |
48 | 51 | */ |
49 | 52 | public class PickBackupFileActivity extends ListActivity |
50 | - implements AdapterView.OnItemClickListener, NotepadConstants, BackupConstants | |
51 | -{ | |
53 | + implements AdapterView.OnItemClickListener, NotepadConstants, BackupConstants { | |
52 | 54 | |
53 | 55 | private static final String LOG_TAG = "simple-notepad"; |
56 | + private static final int REQUEST_EXTERNAL_STORAGE_PERMISSION = 1001; | |
54 | 57 | private static final String MAPPING_KEY_FILE_PATH = "FILE"; |
55 | 58 | private static final String MAPPING_KEY_FILE_NAME = "BASENAME"; |
56 | - private static final String[] MAPPING_FROM = new String[] | |
57 | - { | |
58 | - MAPPING_KEY_FILE_NAME, | |
59 | - }; | |
60 | - private static final int[] MAPPING_TO = new int[] | |
61 | - { | |
62 | - android.R.id.text1, | |
63 | - }; | |
59 | + private static final String[] MAPPING_FROM = new String[]{ | |
60 | + MAPPING_KEY_FILE_NAME,}; | |
61 | + private static final int[] MAPPING_TO = new int[]{ | |
62 | + android.R.id.text1,}; | |
64 | 63 | // instances |
65 | 64 | private final FilenameFilter backupFilenameFilter = new BackupFilenameFilter(); |
66 | 65 | private final List<Map<String, String>> backupFileDataList = new ArrayList<Map<String, String>>(); |
67 | 66 | private SimpleAdapter simpleAdapter; |
68 | 67 | |
69 | 68 | @Override |
70 | - public void onCreate(Bundle savedInstanceState) | |
71 | - { | |
69 | + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { | |
70 | + Log.v(LOG_TAG, "Hello"); | |
71 | + | |
72 | + super.onRequestPermissionsResult(requestCode, permissions, grantResults); | |
73 | + if (requestCode == REQUEST_EXTERNAL_STORAGE_PERMISSION) { | |
74 | + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |
75 | + enableRestoreFunction(); | |
76 | + } | |
77 | + } | |
78 | + | |
79 | + Log.v(LOG_TAG, "Bye"); | |
80 | + } | |
81 | + | |
82 | + @Override | |
83 | + public void onCreate(Bundle savedInstanceState) { | |
72 | 84 | Log.v(LOG_TAG, "Hello"); |
73 | 85 | |
74 | 86 | setTheme(NotepadPreferenceUtils.getTheme(this)); |
@@ -78,37 +90,47 @@ public class PickBackupFileActivity extends ListActivity | ||
78 | 90 | // initialize title |
79 | 91 | Intent intent = getIntent(); |
80 | 92 | String title = intent.getStringExtra(Intent.EXTRA_TITLE); |
81 | - if (title != null) | |
82 | - { | |
93 | + if (title != null) { | |
83 | 94 | setTitle(title); |
84 | 95 | } |
85 | 96 | |
86 | 97 | // initialize list adapter |
87 | 98 | simpleAdapter = new SimpleAdapter(this, backupFileDataList, |
88 | - android.R.layout.simple_list_item_1, | |
89 | - MAPPING_FROM, MAPPING_TO); | |
99 | + android.R.layout.simple_list_item_1, | |
100 | + MAPPING_FROM, MAPPING_TO); | |
90 | 101 | setListAdapter(simpleAdapter); |
91 | 102 | |
92 | 103 | ListView listView = getListView(); |
93 | 104 | listView.setOnItemClickListener(this); |
94 | 105 | |
106 | + if (Build.VERSION.SDK_INT >= 23) { // Android 6.0 or later | |
107 | + if (PermissionUtils.hasExternalStoragePermission(this) == false) { | |
108 | + this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE_PERMISSION); | |
109 | + } | |
110 | + } | |
111 | + | |
95 | 112 | Log.v(LOG_TAG, "Bye"); |
96 | 113 | } |
97 | 114 | |
98 | 115 | @Override |
99 | - protected void onResume() | |
100 | - { | |
116 | + protected void onResume() { | |
101 | 117 | Log.v(LOG_TAG, "Hello"); |
102 | 118 | super.onResume(); |
103 | 119 | |
104 | 120 | updateListData(); |
121 | + if (PermissionUtils.hasExternalStoragePermission(this)) { // Android 6.0 or later | |
122 | + Log.v(LOG_TAG, "hasReadStoragePermission() : true"); | |
123 | + enableRestoreFunction(); | |
124 | + } else { | |
125 | + Log.v(LOG_TAG, "hasReadStoragePermission() : false"); | |
126 | + disableRestoreFunction(); | |
127 | + } | |
105 | 128 | |
106 | 129 | Log.v(LOG_TAG, "Bye"); |
107 | 130 | } |
108 | 131 | |
109 | 132 | @Override |
110 | - public void onItemClick(AdapterView<?> av, View view, int position, long id) | |
111 | - { | |
133 | + public void onItemClick(AdapterView<?> av, View view, int position, long id) { | |
112 | 134 | Log.v(LOG_TAG, "Hello"); |
113 | 135 | |
114 | 136 | Map<String, String> backupFileData = backupFileDataList.get(position); |
@@ -125,25 +147,20 @@ public class PickBackupFileActivity extends ListActivity | ||
125 | 147 | Log.v(LOG_TAG, "Bye"); |
126 | 148 | } |
127 | 149 | |
128 | - private synchronized void updateListData() | |
129 | - { | |
150 | + private synchronized void updateListData() { | |
130 | 151 | Log.v(LOG_TAG, "Hello"); |
131 | 152 | |
132 | 153 | String externalStorageState = Environment.getExternalStorageState(); |
133 | - if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) | |
134 | - { | |
154 | + if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) { | |
135 | 155 | File backupDirPath = Environment.getExternalStorageDirectory(); |
136 | 156 | backupDirPath = new File(backupDirPath, BACKUP_DIR_NAME); |
137 | 157 | Log.d(LOG_TAG, "backupDirPath => " + backupDirPath); |
138 | 158 | |
139 | - if (backupDirPath.exists() && backupDirPath.canRead()) | |
140 | - { | |
159 | + if (backupDirPath.exists() && backupDirPath.canRead()) { | |
141 | 160 | File[] listFiles = backupDirPath.listFiles(backupFilenameFilter); |
142 | - if (listFiles != null) | |
143 | - { | |
161 | + if (listFiles != null) { | |
144 | 162 | backupFileDataList.clear(); |
145 | - for (File file : listFiles) | |
146 | - { | |
163 | + for (File file : listFiles) { | |
147 | 164 | Map<String, String> backupFileData = new HashMap<String, String>(); |
148 | 165 | backupFileData.put(MAPPING_KEY_FILE_PATH, file.getAbsolutePath()); |
149 | 166 | backupFileData.put(MAPPING_KEY_FILE_NAME, file.getName()); |
@@ -154,26 +171,31 @@ public class PickBackupFileActivity extends ListActivity | ||
154 | 171 | } |
155 | 172 | } |
156 | 173 | |
157 | - if (simpleAdapter != null) | |
158 | - { | |
174 | + if (simpleAdapter != null) { | |
159 | 175 | simpleAdapter.notifyDataSetChanged(); |
160 | 176 | } |
161 | 177 | |
162 | 178 | Log.v(LOG_TAG, "Bye"); |
163 | 179 | } |
164 | 180 | |
165 | - class BackupFilenameFilter implements FilenameFilter | |
166 | - { | |
181 | + private void disableRestoreFunction() { | |
182 | + View rationaleView = findViewById(R.id.request_permission_rationale_external_storage_view); | |
183 | + rationaleView.setVisibility(View.VISIBLE); | |
184 | + } | |
185 | + | |
186 | + private void enableRestoreFunction() { | |
187 | + View rationaleView = findViewById(R.id.request_permission_rationale_external_storage_view); | |
188 | + rationaleView.setVisibility(View.GONE); | |
189 | + } | |
190 | + | |
191 | + class BackupFilenameFilter implements FilenameFilter { | |
167 | 192 | |
168 | - public boolean accept(File dir, String name) | |
169 | - { | |
193 | + public boolean accept(File dir, String name) { | |
170 | 194 | boolean result = false; |
171 | - if (name.endsWith(BACKUP_FILE_SUFFIX)) | |
172 | - { | |
195 | + if (name.endsWith(BACKUP_FILE_SUFFIX)) { | |
173 | 196 | String basename = name.substring(0, name.length() - BACKUP_FILE_SUFFIX.length()); |
174 | 197 | Log.d(LOG_TAG, "basename => " + basename); |
175 | - if (basename.length() >= BACKUP_FILE_DATE_FORMAT.length()) | |
176 | - { | |
198 | + if (basename.length() >= BACKUP_FILE_DATE_FORMAT.length()) { | |
177 | 199 | result = true; |
178 | 200 | } |
179 | 201 | } |
@@ -23,15 +23,18 @@ | ||
23 | 23 | */ |
24 | 24 | package org.routine_work.notepad.prefs; |
25 | 25 | |
26 | +import android.Manifest; | |
26 | 27 | import android.app.Activity; |
27 | 28 | import android.content.Intent; |
28 | 29 | import android.net.Uri; |
30 | +import android.os.Build; | |
29 | 31 | import android.os.Bundle; |
30 | 32 | import android.os.Environment; |
31 | 33 | import android.util.Log; |
32 | 34 | import android.view.View; |
33 | 35 | import android.view.View.OnClickListener; |
34 | 36 | import android.widget.Button; |
37 | +import android.widget.TextView; | |
35 | 38 | import android.widget.Toast; |
36 | 39 | import java.io.File; |
37 | 40 | import java.io.FileInputStream; |
@@ -42,8 +45,7 @@ import org.routine_work.notepad.NotepadActivity; | ||
42 | 45 | import org.routine_work.notepad.R; |
43 | 46 | import org.routine_work.notepad.provider.NoteStore; |
44 | 47 | |
45 | -public class RestoreDatabaseActivity extends Activity implements OnClickListener | |
46 | -{ | |
48 | +public class RestoreDatabaseActivity extends Activity implements OnClickListener { | |
47 | 49 | |
48 | 50 | private static final String LOG_TAG = "simple-notepad"; |
49 | 51 | private static final String SAVE_KEY_BACKUP_FILE_PATH = "backupFilePath"; |
@@ -51,11 +53,9 @@ public class RestoreDatabaseActivity extends Activity implements OnClickListener | ||
51 | 53 | private static final int REUQEST_CODE_PICK_BACKUP_FILE = 1; |
52 | 54 | |
53 | 55 | @Override |
54 | - public void onClick(View view) | |
55 | - { | |
56 | + public void onClick(View view) { | |
56 | 57 | int id = view.getId(); |
57 | - switch (id) | |
58 | - { | |
58 | + switch (id) { | |
59 | 59 | case R.id.ok_button: |
60 | 60 | restoreDatabaseFile(); |
61 | 61 | NotepadActivity.quitApplication(this); |
@@ -68,29 +68,23 @@ public class RestoreDatabaseActivity extends Activity implements OnClickListener | ||
68 | 68 | } |
69 | 69 | |
70 | 70 | @Override |
71 | - protected void onCreate(Bundle savedInstanceState) | |
72 | - { | |
71 | + protected void onCreate(Bundle savedInstanceState) { | |
73 | 72 | setTheme(NotepadPreferenceUtils.getTheme(this)); |
74 | 73 | super.onCreate(savedInstanceState); |
75 | 74 | setContentView(R.layout.restore_database_activity); |
76 | 75 | |
77 | - if (savedInstanceState != null) | |
78 | - { | |
76 | + if (savedInstanceState != null) { | |
79 | 77 | backupFilePath = savedInstanceState.getString(SAVE_KEY_BACKUP_FILE_PATH); |
80 | - } | |
81 | - else | |
82 | - { | |
78 | + } else { | |
83 | 79 | Intent intent = getIntent(); |
84 | 80 | Uri data = intent.getData(); |
85 | - if (data != null) | |
86 | - { | |
81 | + if (data != null) { | |
87 | 82 | backupFilePath = data.getPath(); |
88 | 83 | } |
89 | 84 | } |
90 | 85 | Log.d(LOG_TAG, "backupFilePath => " + backupFilePath); |
91 | 86 | |
92 | - if (backupFilePath == null) | |
93 | - { | |
87 | + if (backupFilePath == null) { | |
94 | 88 | Intent pickBackupFileIntent = new Intent(this, PickBackupFileActivity.class); |
95 | 89 | startActivityForResult(pickBackupFileIntent, REUQEST_CODE_PICK_BACKUP_FILE); |
96 | 90 | } |
@@ -104,20 +98,26 @@ public class RestoreDatabaseActivity extends Activity implements OnClickListener | ||
104 | 98 | } |
105 | 99 | |
106 | 100 | @Override |
107 | - protected void onActivityResult(int requestCode, int resultCode, Intent data) | |
108 | - { | |
109 | - switch (requestCode) | |
110 | - { | |
101 | + protected void onResume() { | |
102 | + super.onResume(); //To change body of generated methods, choose Tools | Templates. | |
103 | + if (PermissionUtils.hasExternalStoragePermission(this)) { // Android 6.0 or later | |
104 | + enableRestoreFunction(); | |
105 | + } else { | |
106 | + disableRestoreFunction(); | |
107 | + } | |
108 | + } | |
109 | + | |
110 | + @Override | |
111 | + protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
112 | + switch (requestCode) { | |
111 | 113 | case REUQEST_CODE_PICK_BACKUP_FILE: |
112 | - if (resultCode == RESULT_OK) | |
113 | - { | |
114 | + if (resultCode == RESULT_OK) { | |
114 | 115 | Uri uri = data.getData(); |
115 | 116 | backupFilePath = uri.getPath(); |
116 | 117 | } |
117 | 118 | Log.d(LOG_TAG, "backupFilePath => " + backupFilePath); |
118 | 119 | |
119 | - if (backupFilePath == null) | |
120 | - { | |
120 | + if (backupFilePath == null) { | |
121 | 121 | setResult(RESULT_CANCELED); |
122 | 122 | finish(); |
123 | 123 | } |
@@ -128,46 +128,56 @@ public class RestoreDatabaseActivity extends Activity implements OnClickListener | ||
128 | 128 | } |
129 | 129 | |
130 | 130 | @Override |
131 | - protected void onSaveInstanceState(Bundle outState) | |
132 | - { | |
131 | + protected void onSaveInstanceState(Bundle outState) { | |
133 | 132 | super.onSaveInstanceState(outState); |
134 | 133 | outState.putString(SAVE_KEY_BACKUP_FILE_PATH, backupFilePath); |
135 | 134 | } |
136 | 135 | |
137 | - private void restoreDatabaseFile() | |
138 | - { | |
136 | + private void restoreDatabaseFile() { | |
139 | 137 | Log.d(LOG_TAG, "backupFilePath => " + backupFilePath); |
140 | - if (backupFilePath == null) | |
141 | - { | |
138 | + if (backupFilePath == null) { | |
142 | 139 | Log.e(LOG_TAG, "backup file path is null, the restore was canceled."); |
143 | 140 | return; |
144 | 141 | } |
145 | 142 | |
146 | 143 | String externalStorageState = Environment.getExternalStorageState(); |
147 | - if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) | |
148 | - { | |
144 | + if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) { | |
149 | 145 | File databaseFilePath = NoteStore.getNoteDatabasePath(this); |
150 | 146 | Log.d(LOG_TAG, "databaseFilePath => " + databaseFilePath); |
151 | 147 | |
152 | - try | |
153 | - { | |
148 | + try { | |
154 | 149 | Log.i(LOG_TAG, "Restore database " + backupFilePath + " to " + databaseFilePath); |
155 | 150 | FileChannel inputChannel = new FileInputStream(backupFilePath).getChannel(); |
156 | 151 | FileChannel outputChannel = new FileOutputStream(databaseFilePath).getChannel(); |
157 | 152 | inputChannel.transferTo(0, inputChannel.size(), outputChannel); |
158 | 153 | inputChannel.close(); |
159 | 154 | outputChannel.close(); |
160 | - } | |
161 | - catch (IOException ex) | |
162 | - { | |
155 | + } catch (IOException ex) { | |
163 | 156 | Log.e(LOG_TAG, "The database file copying is failed.", ex); |
164 | 157 | } |
165 | - } | |
166 | - else | |
167 | - { | |
158 | + } else { | |
168 | 159 | String message = "The external storage is not mounted."; |
169 | 160 | Log.e(LOG_TAG, message + "externalStorageState => " + externalStorageState); |
170 | 161 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); |
171 | 162 | } |
172 | 163 | } |
164 | + | |
165 | + private void disableRestoreFunction() { | |
166 | + View rationaleView = findViewById(R.id.request_permission_rationale_external_storage_view); | |
167 | + rationaleView.setVisibility(View.VISIBLE); | |
168 | + | |
169 | + Button okButton = (Button) findViewById(R.id.ok_button); | |
170 | + okButton.setEnabled(false); | |
171 | + | |
172 | + } | |
173 | + | |
174 | + private void enableRestoreFunction() { | |
175 | + // remove permission rationale | |
176 | + View rationaleView = findViewById(R.id.request_permission_rationale_external_storage_view); | |
177 | + rationaleView.setVisibility(View.GONE); | |
178 | + | |
179 | + // enable ok button | |
180 | + Button okButton = (Button) findViewById(R.id.ok_button); | |
181 | + okButton.setEnabled(true); | |
182 | + } | |
173 | 183 | } |
@@ -6,15 +6,24 @@ | ||
6 | 6 | android:layout_height="fill_parent" |
7 | 7 | android:orientation="vertical" |
8 | 8 | > |
9 | - <TextView | |
9 | + <LinearLayout | |
10 | + android:orientation="vertical" | |
10 | 11 | android:layout_width="fill_parent" |
11 | 12 | android:layout_height="wrap_content" |
12 | 13 | android:layout_weight="1" |
13 | 14 | android:padding="4dip" |
14 | - android:text="@string/backup_data_confirm_message" | |
15 | - android:textColor="?android:attr/textColorPrimary" | |
16 | - android:textSize="18sp" | |
17 | - /> | |
15 | + > | |
16 | + <TextView | |
17 | + android:layout_width="fill_parent" | |
18 | + android:layout_height="wrap_content" | |
19 | + android:layout_weight="0" | |
20 | + android:padding="4dip" | |
21 | + android:text="@string/backup_data_confirm_message" | |
22 | + android:textColor="?android:attr/textColorPrimary" | |
23 | + android:textSize="18sp" | |
24 | + /> | |
25 | + <include layout="@layout/request_permission_rationale_external_storage" /> | |
26 | + </LinearLayout> | |
18 | 27 | |
19 | 28 | <View style="@style/hline" /> |
20 | 29 |
@@ -1,8 +1,7 @@ | ||
1 | 1 | <?xml version="1.0" encoding="utf-8"?> |
2 | 2 | <FrameLayout |
3 | 3 | xmlns:android="http://schemas.android.com/apk/res/android" |
4 | - android:layout_width="fill_parent" | |
5 | - android:layout_height="fill_parent" | |
4 | + style="@style/body" | |
6 | 5 | > |
7 | 6 | <ListView |
8 | 7 | android:id="@android:id/list" |
@@ -18,4 +17,10 @@ | ||
18 | 17 | android:layout_gravity="center" |
19 | 18 | android:text="@string/no_backup_file" |
20 | 19 | /> |
20 | + <FrameLayout | |
21 | + android:layout_width="fill_parent" | |
22 | + android:layout_height="fill_parent" | |
23 | + > | |
24 | + <include layout="@layout/request_permission_rationale_external_storage" /> | |
25 | + </FrameLayout> | |
21 | 26 | </FrameLayout> |
\ No newline at end of file |
@@ -2,8 +2,6 @@ | ||
2 | 2 | <FrameLayout |
3 | 3 | xmlns:android="http://schemas.android.com/apk/res/android" |
4 | 4 | style="@style/body" |
5 | - android:layout_width="fill_parent" | |
6 | - android:layout_height="fill_parent" | |
7 | 5 | > |
8 | 6 | |
9 | 7 | <include layout="@layout/note_list" /> |
@@ -0,0 +1,16 @@ | ||
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<FrameLayout | |
3 | + xmlns:android="http://schemas.android.com/apk/res/android" | |
4 | + android:id="@+id/request_permission_rationale_external_storage_view" | |
5 | + android:layout_width="wrap_content" | |
6 | + android:layout_height="wrap_content" | |
7 | +> | |
8 | + <TextView | |
9 | + android:layout_width="wrap_content" | |
10 | + android:layout_height="wrap_content" | |
11 | + android:padding="4dip" | |
12 | + android:text="@string/request_permission_rationale_external_storage" | |
13 | + android:textColor="?android:attr/textColorPrimary" | |
14 | + android:textSize="18sp" | |
15 | + /> | |
16 | +</FrameLayout> | |
\ No newline at end of file |
@@ -6,15 +6,24 @@ | ||
6 | 6 | android:layout_height="fill_parent" |
7 | 7 | android:orientation="vertical" |
8 | 8 | > |
9 | - <TextView | |
9 | + <LinearLayout | |
10 | + android:orientation="vertical" | |
10 | 11 | android:layout_width="fill_parent" |
11 | 12 | android:layout_height="wrap_content" |
12 | 13 | android:layout_weight="1" |
13 | 14 | android:padding="4dip" |
14 | - android:text="@string/restore_data_confirm_message" | |
15 | - android:textColor="?android:attr/textColorPrimary" | |
16 | - android:textSize="18sp" | |
17 | - /> | |
15 | + > | |
16 | + <TextView | |
17 | + android:layout_width="fill_parent" | |
18 | + android:layout_height="wrap_content" | |
19 | + android:layout_weight="0" | |
20 | + android:padding="4dip" | |
21 | + android:text="@string/restore_data_confirm_message" | |
22 | + android:textColor="?android:attr/textColorPrimary" | |
23 | + android:textSize="18sp" | |
24 | + /> | |
25 | + <include layout="@layout/request_permission_rationale_external_storage" /> | |
26 | + </LinearLayout> | |
18 | 27 | |
19 | 28 | <View style="@style/hline" /> |
20 | 29 |
@@ -100,6 +100,7 @@ | ||
100 | 100 | <string name="backup_data_confirm_message">すべてのノートとテンプレートが外部ストレージにバックアップされます。</string> |
101 | 101 | <string name="backup_data_completed_message">ノートとテンプレートのバックアップが完了しました。</string> |
102 | 102 | <string name="external_storage_not_mountted">外部ストレージが接続されていません。</string> |
103 | + <string name="request_permission_rationale_external_storage">バックアップ作成と復元のために、外部ストレージへの読み書きに対して許可が必要です。</string> | |
103 | 104 | <!-- Restore Notes --> |
104 | 105 | <string name="restore_data">データを復元</string> |
105 | 106 | <string name="restore_data_title">データを復元</string> |
@@ -100,6 +100,7 @@ | ||
100 | 100 | <string name="backup_data_confirm_message">All notes and templates will be backed up to the external storage.</string> |
101 | 101 | <string name="backup_data_completed_message">All notes and templates were backed up.</string> |
102 | 102 | <string name="external_storage_not_mountted">The external storage is not mounted.</string> |
103 | + <string name="request_permission_rationale_external_storage">To back up and restore, access permission to the external storage is required.</string> | |
103 | 104 | <!-- Restore Data --> |
104 | 105 | <string name="restore_data">Restore data</string> |
105 | 106 | <string name="restore_data_title">Restore data</string> |