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_FIRST_ENTER_STATION_LIST = "fm_is_first_enter_station_list"; 65 // StorageManager For FM record 66 private static StorageManager sStorageManager = null; 67 68 /** 69 * Whether the frequency is valid. 70 * 71 * @param station The FM station 72 * 73 * @return true if the frequency is in the valid scale, otherwise return 74 * false 75 */ isValidStation(int station)76 public static boolean isValidStation(int station) { 77 boolean isValid = (station >= LOWEST_STATION && station <= HIGHEST_STATION); 78 return isValid; 79 } 80 81 /** 82 * Compute increase station frequency 83 * 84 * @param station The station frequency 85 * 86 * @return station The frequency after increased 87 */ computeIncreaseStation(int station)88 public static int computeIncreaseStation(int station) { 89 int result = station + STEP; 90 if (result > HIGHEST_STATION) { 91 result = LOWEST_STATION; 92 } 93 return result; 94 } 95 96 /** 97 * Compute decrease station frequency 98 * 99 * @param station The station frequency 100 * 101 * @return station The frequency after decreased 102 */ computeDecreaseStation(int station)103 public static int computeDecreaseStation(int station) { 104 int result = station - STEP; 105 if (result < LOWEST_STATION) { 106 result = HIGHEST_STATION; 107 } 108 return result; 109 } 110 111 /** 112 * Compute station value with given frequency 113 * 114 * @param frequency The station frequency 115 * 116 * @return station The result value 117 */ computeStation(float frequency)118 public static int computeStation(float frequency) { 119 return (int) (frequency * CONVERT_RATE); 120 } 121 122 /** 123 * Compute frequency value with given station 124 * 125 * @param station The station value 126 * 127 * @return station The frequency 128 */ computeFrequency(int station)129 public static float computeFrequency(int station) { 130 return (float) station / CONVERT_RATE; 131 } 132 133 /** 134 * According station to get frequency string 135 * 136 * @param station for 100KZ, range 875-1080 137 * 138 * @return string like 87.5 139 */ formatStation(int station)140 public static String formatStation(int station) { 141 float frequency = (float) station / CONVERT_RATE; 142 DecimalFormat decimalFormat = new DecimalFormat("0.0"); 143 return decimalFormat.format(frequency); 144 } 145 146 /** 147 * Get the phone storage path 148 * 149 * @return The phone storage path 150 */ getDefaultStoragePath()151 public static String getDefaultStoragePath() { 152 return Environment.getExternalStorageDirectory().getPath(); 153 } 154 155 /** 156 * Get the default storage state 157 * 158 * @return The default storage state 159 */ getDefaultStorageState(Context context)160 public static String getDefaultStorageState(Context context) { 161 ensureStorageManager(context); 162 String state = sStorageManager.getVolumeState(getDefaultStoragePath()); 163 return state; 164 } 165 ensureStorageManager(Context context)166 private static void ensureStorageManager(Context context) { 167 if (sStorageManager == null) { 168 sStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); 169 } 170 } 171 172 /** 173 * Get the FM play list path 174 * 175 * @param context The context 176 * 177 * @return The FM play list path 178 */ getPlaylistPath(Context context)179 public static String getPlaylistPath(Context context) { 180 ensureStorageManager(context); 181 String[] externalStoragePaths = sStorageManager.getVolumePaths(); 182 String path = externalStoragePaths[0] + "/Playlists/"; 183 return path; 184 } 185 186 /** 187 * Check if has enough space for record 188 * 189 * @param recordingSdcard The recording sdcard path 190 * 191 * @return true if has enough space for record 192 */ hasEnoughSpace(String recordingSdcard)193 public static boolean hasEnoughSpace(String recordingSdcard) { 194 boolean ret = false; 195 try { 196 StatFs fs = new StatFs(recordingSdcard); 197 long blocks = fs.getAvailableBlocks(); 198 long blockSize = fs.getBlockSize(); 199 long spaceLeft = blocks * blockSize; 200 ret = spaceLeft > LOW_SPACE_THRESHOLD ? true : false; 201 } catch (IllegalArgumentException e) { 202 Log.e(TAG, "hasEnoughSpace, sdcard may be unmounted:" + recordingSdcard); 203 } 204 return ret; 205 } 206 207 /** 208 * Get the latest searched location 209 * @return the list of latitude and longitude 210 */ getLastSearchedLocation(Context context)211 public static double[] getLastSearchedLocation(Context context) { 212 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 213 214 String strLatitude = prefs.getString(FM_LOCATION_LATITUDE, "0.0"); 215 String strLongitude = prefs.getString(FM_LOCATION_LONGITUDE, "0.0"); 216 double latitude = Double.valueOf(strLatitude); 217 double longitude = Double.valueOf(strLongitude); 218 return new double[] { latitude, longitude }; 219 } 220 221 /** 222 * Set the last searched location 223 */ setLastSearchedLocation(Context context, double latitude, double longitude)224 public static void setLastSearchedLocation(Context context, double latitude, double longitude) { 225 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 226 SharedPreferences.Editor editor = prefs.edit(); 227 String strLatitude = Double.valueOf(latitude).toString(); 228 String strLongitude = Double.valueOf(longitude).toString(); 229 editor.putString(FM_LOCATION_LATITUDE, strLatitude); 230 editor.putString(FM_LOCATION_LONGITUDE, strLongitude); 231 editor.commit(); 232 } 233 234 /** 235 * check it is the first time to use Fm 236 */ isFirstTimePlayFm(Context context)237 public static boolean isFirstTimePlayFm(Context context) { 238 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 239 boolean isFirstTime = prefs.getBoolean(FM_IS_FIRST_TIME_PLAY, true); 240 return isFirstTime; 241 } 242 243 /** 244 * Called when first time play FM. 245 * @param context The context 246 */ setIsFirstTimePlayFm(Context context)247 public static void setIsFirstTimePlayFm(Context context) { 248 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 249 SharedPreferences.Editor editor = prefs.edit(); 250 editor.putBoolean(FM_IS_FIRST_TIME_PLAY, false); 251 editor.commit(); 252 } 253 254 /** 255 * check it is the first time enter into station list page 256 */ isFirstEnterStationList(Context context)257 public static boolean isFirstEnterStationList(Context context) { 258 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 259 boolean isFirstEnter = prefs.getBoolean(FM_IS_FIRST_ENTER_STATION_LIST, true); 260 if (isFirstEnter) { 261 SharedPreferences.Editor editor = prefs.edit(); 262 editor.putBoolean(FM_IS_FIRST_ENTER_STATION_LIST, false); 263 editor.commit(); 264 } 265 return isFirstEnter; 266 } 267 268 /** 269 * Create the notification large icon bitmap from layout 270 * @param c The context 271 * @param text The frequency text 272 * @return The large icon bitmap with frequency text 273 */ createNotificationLargeIcon(Context c, String text)274 public static Bitmap createNotificationLargeIcon(Context c, String text) { 275 Resources res = c.getResources(); 276 int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width); 277 int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height); 278 LinearLayout iconLayout = new LinearLayout(c); 279 iconLayout.setOrientation(LinearLayout.VERTICAL); 280 iconLayout.setBackgroundColor(c.getResources().getColor(R.color.theme_primary_color)); 281 iconLayout.setDrawingCacheEnabled(true); 282 iconLayout.layout(0, 0, width, height); 283 TextView iconText = new TextView(c); 284 iconText.setTextSize(24.0f); 285 iconText.setTextColor(res.getColor(R.color.theme_title_color)); 286 iconText.setText(text); 287 iconText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 288 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 289 int left = (int) ((width - iconText.getMeasuredWidth()) * 0.5); 290 int top = (int) ((height - iconText.getMeasuredHeight()) * 0.5); 291 iconText.layout(left, top, iconText.getMeasuredWidth() + left, 292 iconText.getMeasuredHeight() + top); 293 iconLayout.addView(iconText); 294 iconLayout.layout(0, 0, width, height); 295 296 iconLayout.buildDrawingCache(); 297 Bitmap largeIcon = Bitmap.createBitmap(iconLayout.getDrawingCache()); 298 iconLayout.destroyDrawingCache(); 299 return largeIcon; 300 } 301 } 302