blob: b6219fd2245fb2b069f68f6bec68136f119e0289 [file] [log] [blame]
Benson Huanga8b6afc2014-11-20 15:42:26 +08001/*
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
17package com.android.fmradio;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.content.res.Resources;
22import android.graphics.Bitmap;
23import android.os.Environment;
24import android.os.StatFs;
25import android.os.storage.StorageManager;
26import android.preference.PreferenceManager;
27import android.util.Log;
28import android.view.View.MeasureSpec;
29import android.widget.LinearLayout;
30import android.widget.TextView;
31
Tony Kuoc7cf5012015-02-10 20:34:46 +080032import java.text.DecimalFormat;
Benson Huanga8b6afc2014-11-20 15:42:26 +080033import java.util.Locale;
34
35/**
36 * This class provider interface to compute station and frequency, get project
37 * string
38 */
39public 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";
Benson Huang4f33aa32015-03-18 10:21:54 +080064 private static final String FM_IS_SPEAKER_MODE = "fm_is_speaker_mode";
Benson Huanga8b6afc2014-11-20 15:42:26 +080065 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;
Tony Kuoc7cf5012015-02-10 20:34:46 +0800143 DecimalFormat decimalFormat = new DecimalFormat("0.0");
144 return decimalFormat.format(frequency);
Benson Huanga8b6afc2014-11-20 15:42:26 +0800145 }
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 }
Benson Huang4f33aa32015-03-18 10:21:54 +0800302
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 }
Benson Huanga8b6afc2014-11-20 15:42:26 +0800325}