Home | History | Annotate | Download | only in fmradio
      1 /*
      2  * Copyright (C) 2014 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.android.fmradio;
     18 
     19 import android.content.Context;
     20 import android.content.SharedPreferences;
     21 import android.content.res.Resources;
     22 import android.graphics.Bitmap;
     23 import android.os.Environment;
     24 import android.os.StatFs;
     25 import android.os.storage.StorageManager;
     26 import android.preference.PreferenceManager;
     27 import android.util.Log;
     28 import android.view.View.MeasureSpec;
     29 import android.widget.LinearLayout;
     30 import android.widget.TextView;
     31 
     32 import java.text.DecimalFormat;
     33 import java.util.Locale;
     34 
     35 /**
     36  * This class provider interface to compute station and frequency, get project
     37  * string
     38  */
     39 public class FmUtils {
     40     private static final String TAG = "FmUtils";
     41 
     42     // FM station variables
     43     public static final int DEFAULT_STATION = 1000;
     44     public static final float DEFAULT_STATION_FLOAT = computeFrequency(DEFAULT_STATION);
     45     // maximum station frequency
     46     private static final int HIGHEST_STATION = 1080;
     47     // minimum station frequency
     48     private static final int LOWEST_STATION = 875;
     49     // station step
     50     private static final int STEP = 1;
     51     // convert rate
     52     private static final int CONVERT_RATE = 10;
     53 
     54     // minimum storage space for record (512KB).
     55     // Need to check before starting recording and during recording to avoid
     56     // recording keeps going but there is no free space in sdcard.
     57     public static final long LOW_SPACE_THRESHOLD = 512 * 1024;
     58     // Different city may have different RDS information.
     59     // We define 100 miles (160934.4m) to distinguish the cities.
     60     public static final double LOCATION_DISTANCE_EXCEED = 160934.4;
     61     private static final String FM_LOCATION_LATITUDE = "fm_location_latitude";
     62     private static final String FM_LOCATION_LONGITUDE = "fm_location_longitude";
     63     private static final String FM_IS_FIRST_TIME_PLAY = "fm_is_first_time_play";
     64     private static final String FM_IS_SPEAKER_MODE = "fm_is_speaker_mode";
     65     private static final String FM_IS_FIRST_ENTER_STATION_LIST = "fm_is_first_enter_station_list";
     66     // StorageManager For FM record
     67     private static StorageManager sStorageManager = null;
     68 
     69     /**
     70      * Whether the frequency is valid.
     71      *
     72      * @param station The FM station
     73      *
     74      * @return true if the frequency is in the valid scale, otherwise return
     75      *         false
     76      */
     77     public static boolean isValidStation(int station) {
     78         boolean isValid = (station >= LOWEST_STATION && station <= HIGHEST_STATION);
     79         return isValid;
     80     }
     81 
     82     /**
     83      * Compute increase station frequency
     84      *
     85      * @param station The station frequency
     86      *
     87      * @return station The frequency after increased
     88      */
     89     public static int computeIncreaseStation(int station) {
     90         int result = station + STEP;
     91         if (result > HIGHEST_STATION) {
     92             result = LOWEST_STATION;
     93         }
     94         return result;
     95     }
     96 
     97     /**
     98      * Compute decrease station frequency
     99      *
    100      * @param station The station frequency
    101      *
    102      * @return station The frequency after decreased
    103      */
    104     public static int computeDecreaseStation(int station) {
    105         int result = station - STEP;
    106         if (result < LOWEST_STATION) {
    107             result = HIGHEST_STATION;
    108         }
    109         return result;
    110     }
    111 
    112     /**
    113      * Compute station value with given frequency
    114      *
    115      * @param frequency The station frequency
    116      *
    117      * @return station The result value
    118      */
    119     public static int computeStation(float frequency) {
    120         return (int) (frequency * CONVERT_RATE);
    121     }
    122 
    123     /**
    124      * Compute frequency value with given station
    125      *
    126      * @param station The station value
    127      *
    128      * @return station The frequency
    129      */
    130     public static float computeFrequency(int station) {
    131         return (float) station / CONVERT_RATE;
    132     }
    133 
    134     /**
    135      * According station to get frequency string
    136      *
    137      * @param station for 100KZ, range 875-1080
    138      *
    139      * @return string like 87.5
    140      */
    141     public static String formatStation(int station) {
    142         float frequency = (float) station / CONVERT_RATE;
    143         DecimalFormat decimalFormat = new DecimalFormat("0.0");
    144         return decimalFormat.format(frequency);
    145     }
    146 
    147     /**
    148      * Get the phone storage path
    149      *
    150      * @return The phone storage path
    151      */
    152     public static String getDefaultStoragePath() {
    153         return Environment.getExternalStorageDirectory().getPath();
    154     }
    155 
    156     /**
    157      * Get the default storage state
    158      *
    159      * @return The default storage state
    160      */
    161     public static String getDefaultStorageState(Context context) {
    162         ensureStorageManager(context);
    163         String state = sStorageManager.getVolumeState(getDefaultStoragePath());
    164         return state;
    165     }
    166 
    167     private static void ensureStorageManager(Context context) {
    168         if (sStorageManager == null) {
    169             sStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    170         }
    171     }
    172 
    173     /**
    174      * Get the FM play list path
    175      *
    176      * @param context The context
    177      *
    178      * @return The FM play list path
    179      */
    180     public static String getPlaylistPath(Context context) {
    181         ensureStorageManager(context);
    182         String[] externalStoragePaths = sStorageManager.getVolumePaths();
    183         String path = externalStoragePaths[0] + "/Playlists/";
    184         return path;
    185     }
    186 
    187     /**
    188      * Check if has enough space for record
    189      *
    190      * @param recordingSdcard The recording sdcard path
    191      *
    192      * @return true if has enough space for record
    193      */
    194     public static boolean hasEnoughSpace(String recordingSdcard) {
    195         boolean ret = false;
    196         try {
    197             StatFs fs = new StatFs(recordingSdcard);
    198             long blocks = fs.getAvailableBlocks();
    199             long blockSize = fs.getBlockSize();
    200             long spaceLeft = blocks * blockSize;
    201             ret = spaceLeft > LOW_SPACE_THRESHOLD ? true : false;
    202         } catch (IllegalArgumentException e) {
    203             Log.e(TAG, "hasEnoughSpace, sdcard may be unmounted:" + recordingSdcard);
    204         }
    205         return ret;
    206     }
    207 
    208     /**
    209      * Get the latest searched location
    210      * @return the list of latitude and longitude
    211      */
    212     public static double[] getLastSearchedLocation(Context context) {
    213         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    214 
    215         String strLatitude = prefs.getString(FM_LOCATION_LATITUDE, "0.0");
    216         String strLongitude = prefs.getString(FM_LOCATION_LONGITUDE, "0.0");
    217         double latitude = Double.valueOf(strLatitude);
    218         double longitude = Double.valueOf(strLongitude);
    219         return new double[] { latitude, longitude };
    220     }
    221 
    222     /**
    223      * Set the last searched location
    224      */
    225     public static void setLastSearchedLocation(Context context, double latitude, double longitude) {
    226         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    227         SharedPreferences.Editor editor = prefs.edit();
    228         String strLatitude = Double.valueOf(latitude).toString();
    229         String strLongitude = Double.valueOf(longitude).toString();
    230         editor.putString(FM_LOCATION_LATITUDE, strLatitude);
    231         editor.putString(FM_LOCATION_LONGITUDE, strLongitude);
    232         editor.commit();
    233     }
    234 
    235     /**
    236      * check it is the first time to use Fm
    237      */
    238     public static boolean isFirstTimePlayFm(Context context) {
    239         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    240         boolean isFirstTime = prefs.getBoolean(FM_IS_FIRST_TIME_PLAY, true);
    241         return isFirstTime;
    242     }
    243 
    244     /**
    245      * Called when first time play FM.
    246      * @param context The context
    247      */
    248     public static void setIsFirstTimePlayFm(Context context) {
    249         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    250         SharedPreferences.Editor editor = prefs.edit();
    251         editor.putBoolean(FM_IS_FIRST_TIME_PLAY, false);
    252         editor.commit();
    253     }
    254 
    255     /**
    256      * check it is the first time enter into station list page
    257      */
    258     public static boolean isFirstEnterStationList(Context context) {
    259         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    260         boolean isFirstEnter = prefs.getBoolean(FM_IS_FIRST_ENTER_STATION_LIST, true);
    261         if (isFirstEnter) {
    262             SharedPreferences.Editor editor = prefs.edit();
    263             editor.putBoolean(FM_IS_FIRST_ENTER_STATION_LIST, false);
    264             editor.commit();
    265         }
    266         return isFirstEnter;
    267     }
    268 
    269     /**
    270      * Create the notification large icon bitmap from layout
    271      * @param c The context
    272      * @param text The frequency text
    273      * @return The large icon bitmap with frequency text
    274      */
    275     public static Bitmap createNotificationLargeIcon(Context c, String text) {
    276         Resources res = c.getResources();
    277         int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width);
    278         int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height);
    279         LinearLayout iconLayout = new LinearLayout(c);
    280         iconLayout.setOrientation(LinearLayout.VERTICAL);
    281         iconLayout.setBackgroundColor(c.getResources().getColor(R.color.theme_primary_color));
    282         iconLayout.setDrawingCacheEnabled(true);
    283         iconLayout.layout(0, 0, width, height);
    284         TextView iconText = new TextView(c);
    285         iconText.setTextSize(24.0f);
    286         iconText.setTextColor(res.getColor(R.color.theme_title_color));
    287         iconText.setText(text);
    288         iconText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
    289                 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    290         int left = (int) ((width - iconText.getMeasuredWidth()) * 0.5);
    291         int top = (int) ((height - iconText.getMeasuredHeight()) * 0.5);
    292         iconText.layout(left, top, iconText.getMeasuredWidth() + left,
    293                 iconText.getMeasuredHeight() + top);
    294         iconLayout.addView(iconText);
    295         iconLayout.layout(0, 0, width, height);
    296 
    297         iconLayout.buildDrawingCache();
    298         Bitmap largeIcon = Bitmap.createBitmap(iconLayout.getDrawingCache());
    299         iconLayout.destroyDrawingCache();
    300         return largeIcon;
    301     }
    302 
    303     /**
    304      * Get whether speaker mode is in use when audio focus lost.
    305      * @param context the Context
    306      * @return true for speaker mode, false for non speaker mode
    307      */
    308     public static boolean getIsSpeakerModeOnFocusLost(Context context) {
    309         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    310 
    311         return prefs.getBoolean(FM_IS_SPEAKER_MODE, false);
    312     }
    313 
    314     /**
    315      * Set whether speaker mode is in use.
    316      * @param context the Context
    317      * @param isSpeaker speaker state
    318      */
    319     public static void setIsSpeakerModeOnFocusLost(Context context, boolean isSpeaker) {
    320         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    321         SharedPreferences.Editor editor = prefs.edit();
    322         editor.putBoolean(FM_IS_SPEAKER_MODE, isSpeaker);
    323         editor.commit();
    324     }
    325 }
    326