Home | History | Annotate | Download | only in com.example.android.autobackupsample
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.autobackupsample;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.os.Bundle;
     22 import android.text.TextUtils;
     23 import android.util.Log;
     24 import android.view.Gravity;
     25 import android.view.View;
     26 import android.widget.AdapterView;
     27 import android.widget.ArrayAdapter;
     28 import android.widget.EditText;
     29 import android.widget.Spinner;
     30 import android.widget.Toast;
     31 
     32 import com.example.android.autobackupsample.MainActivityFragment;
     33 
     34 import java.io.BufferedOutputStream;
     35 import java.io.File;
     36 import java.io.FileOutputStream;
     37 
     38 /**
     39  * The purpose of AddFileActivity activity is to create a data file based on the
     40  * file name and size parameters specified as an Intent external parameters or with the
     41  * activity UI.
     42  * <p/>
     43  * The optional intent parameters are
     44  * {@link com.example.android.autobackupsample.AddFileActivity#FILE_NAME} and
     45  * {@link com.example.android.autobackupsample.AddFileActivity#FILE_SIZE_IN_BYTES}.
     46  * {@link com.example.android.autobackupsample.AddFileActivity#FILE_STORAGE}.
     47  * <p/>
     48  * The activity will return an
     49  * {@link com.example.android.autobackupsample.MainActivityFragment#ADD_FILE_RESULT_ERROR}
     50  * if intent parameters are specified incorrectly or it will display Toast messages to the user
     51  * if those parameters are specified via the activity UI.
     52  */
     53 public class AddFileActivity extends Activity {
     54 
     55     private static final String TAG = "AutoBackupSample";
     56 
     57     /**
     58      * The intent parameter that specifies a file name. The file name must be unique for the
     59      * application internal directory.
     60      */
     61     public static final String FILE_NAME = "file_name";
     62 
     63     /**
     64      * The intent parameter that specifies a file size in bytes. The size must be a number
     65      * larger or equal to 0.
     66      */
     67     public static final String FILE_SIZE_IN_BYTES = "file_size_in_bytes";
     68 
     69     /**
     70      * The file storage is an optional parameter. It should be one of these:
     71      * "INTERNAL", "EXTERNAL", "DONOTBACKUP". The default option is "INTERNAL".
     72      */
     73     public static final String FILE_STORAGE = "file_storage";
     74 
     75     /**
     76      * A file size multiplier. It is used to calculate the total number of bytes to be added
     77      * to the file.
     78      */
     79     private int mSizeMultiplier = 1;
     80 
     81     /**
     82      * Defines File Storage options.
     83      */
     84     private static enum FileStorage {
     85         INTERNAL,
     86         EXTERNAL,
     87         DONOTBACKUP;
     88     }
     89 
     90     /**
     91      * Contains a selected by a user file storage option.
     92      */
     93     private FileStorage mFileStorage = FileStorage.INTERNAL;
     94 
     95     @Override
     96     public void onCreate(Bundle savedInstanceState) {
     97         super.onCreate(savedInstanceState);
     98         setContentView(R.layout.add_file);
     99         initFileSizeSpinner();
    100         initFileStorageSpinner();
    101     }
    102 
    103     @Override
    104     protected void onResume() {
    105         super.onResume();
    106         // If an intent has extra parameters, create the file and finish the activity.
    107         if (getIntent().hasExtra(FILE_NAME) && getIntent().hasExtra(FILE_SIZE_IN_BYTES)) {
    108             String fileName = getIntent().getStringExtra(FILE_NAME);
    109             String sizeInBytesParamValue = getIntent().getStringExtra(FILE_SIZE_IN_BYTES);
    110             String fileStorageParamValue = FileStorage.INTERNAL.toString();
    111 
    112             if (getIntent().hasExtra(FILE_STORAGE)) {
    113                 fileStorageParamValue = getIntent().getStringExtra(FILE_STORAGE);
    114             }
    115 
    116             if (TextUtils.isEmpty(fileName) ||
    117                     isFileExists(fileName) ||
    118                     !isSizeValid(sizeInBytesParamValue) ||
    119                     !isFileStorageParamValid(fileStorageParamValue)) {
    120                 setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
    121                 finish();
    122                 return;
    123             }
    124 
    125             mFileStorage = FileStorage.valueOf(fileStorageParamValue);
    126 
    127             if (mFileStorage == FileStorage.EXTERNAL && !Utils.isExternalStorageAvailable()) {
    128                 setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
    129                 finish();
    130                 return;
    131             }
    132 
    133             createFileWithRandomDataAndFinishActivity(fileName, mFileStorage,
    134                     sizeInBytesParamValue);
    135         }
    136     }
    137 
    138     /**
    139      * A handler function for a Create File button click event.
    140      *
    141      * @param view a reference to the Create File button view.
    142      */
    143     public void onCreateFileButtonClick(View view) {
    144         EditText fileNameEditText = (EditText) findViewById(R.id.file_name);
    145         EditText fileSizeEditText = (EditText) findViewById(R.id.file_size);
    146         String fileName = fileNameEditText.getText().toString();
    147         String fileSizeEditTextValue = fileSizeEditText.getText().toString();
    148 
    149         if (TextUtils.isEmpty(fileName) || isFileExists(fileName)) {
    150             Toast toast = Toast.makeText(this, getText(R.string.file_exists), Toast.LENGTH_LONG);
    151             toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
    152             toast.show();
    153             return;
    154         }
    155 
    156         if (!isSizeValid(fileSizeEditTextValue)) {
    157             Toast toast = Toast.makeText(this, getText(R.string.file_size_is_invalid),
    158                     Toast.LENGTH_LONG);
    159             toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
    160             toast.show();
    161             return;
    162         }
    163 
    164         long fileSize = Integer.parseInt(fileSizeEditTextValue) * mSizeMultiplier;
    165 
    166         if (mFileStorage == FileStorage.EXTERNAL && !Utils.isExternalStorageAvailable()) {
    167             Toast toast = Toast.makeText(this,
    168                     getText(R.string.external_storage_unavailable), Toast.LENGTH_LONG);
    169             toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
    170             toast.show();
    171             return;
    172         }
    173 
    174         createFileWithRandomDataAndFinishActivity(fileName, mFileStorage, String.valueOf(fileSize));
    175     }
    176 
    177     private void initFileSizeSpinner() {
    178         Spinner spinner = (Spinner) findViewById(R.id.file_size_spinner);
    179         final ArrayAdapter<CharSequence> adapter =
    180                 ArrayAdapter.createFromResource(this, R.array.file_size_array,
    181                         android.R.layout.simple_spinner_item);
    182         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    183         spinner.setAdapter(adapter);
    184         spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    185             @Override
    186             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    187                 String sizeMeasure = adapter.getItem(position).toString();
    188                 mSizeMultiplier = (int) Math.pow(1024, position);
    189                 if (Log.isLoggable(TAG, Log.DEBUG)) {
    190                     Log.d(TAG, String.format("Selected: %s, %d", sizeMeasure,
    191                             mSizeMultiplier));
    192                 }
    193             }
    194 
    195             @Override
    196             public void onNothingSelected(AdapterView<?> parent) {
    197 
    198             }
    199         });
    200     }
    201 
    202     private void initFileStorageSpinner() {
    203         Spinner spinner = (Spinner) findViewById(R.id.storage_spinner);
    204         final ArrayAdapter<CharSequence> adapter =
    205                 ArrayAdapter.createFromResource(this, R.array.file_storage_array,
    206                         android.R.layout.simple_spinner_item);
    207         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    208         spinner.setAdapter(adapter);
    209         spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    210             @Override
    211             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    212                 mFileStorage = FileStorage.values()[position];
    213             }
    214 
    215             @Override
    216             public void onNothingSelected(AdapterView<?> parent) {
    217 
    218             }
    219         });
    220     }
    221 
    222     private void createFileWithRandomDataAndFinishActivity(String fileName, FileStorage storage,
    223                                                            String sizeInBytes) {
    224         long size = Long.valueOf(sizeInBytes);
    225         File file = null;
    226         FileOutputStream out = null;
    227         BufferedOutputStream bufOut = null;
    228         try {
    229             switch (storage) {
    230                 case INTERNAL:
    231                     file = getInternalFile(fileName);
    232                     out = openFileOutput(file.getName(), Context.MODE_PRIVATE);
    233                     break;
    234                 case EXTERNAL:
    235                     assert Utils.isExternalStorageAvailable() :
    236                             "The external storage is not available";
    237                     File externalAppDir = getExternalFilesDir(null);
    238                     file = new File(externalAppDir, fileName);
    239                     out = new FileOutputStream(file);
    240                     break;
    241                 case DONOTBACKUP:
    242                     file = new File(getNoBackupFilesDir(), fileName);
    243                     out = new FileOutputStream(file);
    244                     break;
    245             }
    246 
    247             if (file == null || out == null) {
    248                 Log.d(TAG, "Unable to create file output stream");
    249                 // Returning back to the caller activity.
    250                 setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
    251                 finish();
    252                 return;
    253             }
    254 
    255             bufOut = new BufferedOutputStream(out);
    256             for (int i = 0; i < size; i++) {
    257                 byte b = (byte) (255 * Math.random());
    258                 bufOut.write(b);
    259             }
    260 
    261             String message = String.format("File created: %s, size: %s bytes",
    262                     file.getAbsolutePath(), sizeInBytes);
    263 
    264             Toast toast = Toast.makeText(this, message, Toast.LENGTH_LONG);
    265             toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
    266             toast.show();
    267             Log.d(TAG, message);
    268 
    269             // Returning back to the caller activity.
    270             setResult(MainActivityFragment.ADD_FILE_RESULT_SUCCESS);
    271             finish();
    272         } catch (Exception e) {
    273             Log.e(TAG, e.getMessage(), e);
    274             // Returning back to the caller activity.
    275             setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
    276             finish();
    277         } finally {
    278             if (bufOut != null) {
    279                 try {
    280                     bufOut.close();
    281                 } catch (Exception e) {
    282                     // Ignore.
    283                 }
    284             }
    285         }
    286     }
    287 
    288     private boolean isFileExists(String fileName) {
    289         File file = getInternalFile(fileName);
    290         if (file.exists()) {
    291             if (Log.isLoggable(TAG, Log.DEBUG)) {
    292                 Log.d(TAG, "This file exists: " + file.getName());
    293             }
    294             return true;
    295         }
    296         return false;
    297     }
    298 
    299     private boolean isSizeValid(String sizeInBytesParamValue) {
    300         long sizeInBytes = 0;
    301         try {
    302             sizeInBytes = Long.valueOf(sizeInBytesParamValue);
    303         } catch (NumberFormatException e) {
    304             if (Log.isLoggable(TAG, Log.DEBUG)) {
    305                 Log.d(TAG, "Invalid file size: " + sizeInBytesParamValue);
    306             }
    307             return false;
    308         }
    309 
    310         // Validate file size value. It should be 0 or a positive number.
    311         if (sizeInBytes < 0) {
    312             if (Log.isLoggable(TAG, Log.DEBUG)) {
    313                 Log.d(TAG, "Invalid file size: " + sizeInBytes);
    314             }
    315             return false;
    316         }
    317         return true;
    318     }
    319 
    320     private boolean isFileStorageParamValid(String fileStorage) {
    321         try {
    322             mFileStorage = FileStorage.valueOf(fileStorage);
    323         } catch (IllegalArgumentException e) {
    324             if (Log.isLoggable(TAG, Log.DEBUG)) {
    325                 Log.d(TAG, "Invalid file storage: " + fileStorage);
    326             }
    327             return false;
    328         }
    329         return true;
    330     }
    331 
    332     private File getInternalFile(String fileName) {
    333         File internalAppDir = getFilesDir();
    334         return new File(internalAppDir, fileName);
    335     }
    336 
    337 }