“翻转静音”的Android实现 android 翻转静音
有朋友很想要Symbian系统上来电话时翻转静音的功能,于是帮其实现之。
因其手机为Android1.5版本,所以使用了部分老旧的API,参考时请注意。
要求功能:
设置是否开启翻转静音功能——上图“电话”选项。
设置功能开始状态下在托盘区是否显示图标——上图“托盘图标”选项。
设置触发静音的翻转角度——上图“翻转触发角度”选项,另点击“当前手机角度”可直接将触发角度设为当前手机倾斜角度。
详细见下图:
程序设计:
主体结构
提供用户设置的界面——TurnSilenceActivity
在后台运行,来电话时监视翻转进行静音的服务——TurnSilenceService
接受系统消息,在开机时启动翻转静音服务——TurnSilenceReceiver
主要技术
获知来电话事件——PhoneStateListener
获取手机倾斜角度——TYPE_ACCELEROMETER
改变手机振铃模式——AUDIO_SERVICE
显示托盘图标——NOTIFICATION_SERVICE
保存用户设定——SharedPreferences
详细见下图:
代码实现:
TurnSilenceReceiver.java
public class TurnSilenceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
TurnSilenceResource mTsRes = new TurnSilenceResource(context);
boolean optCallFlg = mTsRes.getOptCallValue();
if (true == optCallFlg) {
TurnSilenceUtility.startService(mTsRes, TurnSilenceService.class,
TurnSilenceActivity.class);
}
}
}TurnSilenceActivity.java
public class TurnSilenceActivity extends PreferenceActivity implements
OnPreferenceChangeListener, OnPreferenceClickListener {
private SensorManager mSensorMgr;
private Sensor mGravitySensor;
private double mDegreeDbl;
private TurnSilenceResource mTsRes;
private EditTextPreference mOptTriggerDegreeEditTextPref;
private Preference mOptRealDegreePref;
private final SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
double g = TurnSilenceUtility.GRAVITY;
double degreeDbl;
String degreeStr;
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
degreeDbl = event.values[SensorManager.DATA_Z];
if (g < Math.abs(degreeDbl)) {
g = Math.abs(degreeDbl);
}
degreeDbl = Math.asin(degreeDbl / g);
mDegreeDbl = degreeDbl * TurnSilenceUtility.DEGREE_PI / Math.PI;
degreeStr = String.format(mTsRes.getOptRealDegreeFormat(),
mDegreeDbl);
mOptRealDegreePref.setSummary(degreeStr);
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.options);
mTsRes = new TurnSilenceResource(this);
getPreferenceScreen().findPreference(mTsRes.getOptCallKey())
.setOnPreferenceChangeListener(this);
mOptRealDegreePref = getPreferenceScreen().findPreference(
mTsRes.getOptRealDegreeKey());
mOptRealDegreePref.setOnPreferenceClickListener(this);
mOptTriggerDegreeEditTextPref = (EditTextPreference) getPreferenceScreen()
.findPreference(mTsRes.getOptTriggerDegreeKey());
mOptTriggerDegreeEditTextPref.setOnPreferenceChangeListener(this);
if (true == mTsRes.getOptCallValue()) {
TurnSilenceUtility.startService(mTsRes, TurnSilenceService.class,
TurnSilenceActivity.class);
}
mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mGravitySensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
@Override
protected void onResume() {
super.onResume();
mSensorMgr.registerListener(mSensorEventListener, mGravitySensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
mSensorMgr.unregisterListener(mSensorEventListener);
super.onPause();
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key;
boolean ret = false;
key = preference.getKey();
if (mTsRes.getOptCallKey().equals(key)) {
if (true == mTsRes.getOptCallValue()) {
TurnSilenceUtility
.stopService(mTsRes, TurnSilenceService.class);
} else {
TurnSilenceUtility.startService(mTsRes,
TurnSilenceService.class, TurnSilenceActivity.class);
}
ret = true;
} else if (mTsRes.getOptTriggerDegreeKey().equals(key)) {
try {
Double.parseDouble((String) newValue);
ret = true;
} catch (NumberFormatException e) {
ret = false;
}
}
return ret;
}
@Override
public boolean onPreferenceClick(Preference preference) {
String key = preference.getKey();
if (mTsRes.getOptRealDegreeKey().equals(key)) {
String degreeStr;
degreeStr = Double.toString(mDegreeDbl);
mOptTriggerDegreeEditTextPref.setText(degreeStr);
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_about:
startActivity(new Intent(this, TurnSilenceAbout.class));
return true;
case R.id.item_exit:
mSensorMgr.unregisterListener(mSensorEventListener);
finish();
return true;
}
return false;
}
}TurnSilenceService.java
public class TurnSilenceService extends Service implements
OnSharedPreferenceChangeListener {
private NotificationManager mNotificationMgr;
private TelephonyManager mTelephonyMgr;
private AudioManager mAudioMgr;
private SensorManager mSensorMgr;
private Sensor mGravitySensor;
private boolean mGravitySensorFlg = false;
private boolean mUpwardFlg = false;
private int mRingerMode;
private double mTriggerDegree;
private TurnSilenceResource mTsRes;
private Class<?> mMainClass;
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(final int state,
final String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
if (false == mGravitySensorFlg) {
mRingerMode = mAudioMgr.getRingerMode();
if (AudioManager.RINGER_MODE_SILENT != mRingerMode) {
mSensorMgr.registerListener(mSensorEventListener,
mGravitySensor,
SensorManager.SENSOR_DELAY_NORMAL);
mGravitySensorFlg = true;
}
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_IDLE:
if (true == mGravitySensorFlg) {
mSensorMgr.unregisterListener(mSensorEventListener);
mAudioMgr.setRingerMode(mRingerMode);
mGravitySensorFlg = false;
}
break;
default:
break;
}
}
};
private final SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if (event.values[SensorManager.DATA_Z] >= mTriggerDegree) {
mUpwardFlg = true;
} else {
if (true == mUpwardFlg) {
mAudioMgr
.setRingerMode(AudioManager.RINGER_MODE_SILENT);
mUpwardFlg = false;
}
}
}
}
};
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mTsRes = new TurnSilenceResource(this);
mTsRes.regOnSharedPrefChangeListener(this);
mTriggerDegree = getTriggerDegree();
mTelephonyMgr = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyMgr.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
mAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mGravitySensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mNotificationMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void onStart(Intent intent, int startId) {
String str;
str = intent.getExtras().getString(mTsRes.getDataMainClassKey());
try {
mMainClass = Class.forName(str);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (true == mTsRes.getOptTrayValue()) {
showTrayIcon();
}
}
@Override
public void onDestroy() {
if (true == mGravitySensorFlg) {
mSensorMgr.unregisterListener(mSensorEventListener);
mAudioMgr.setRingerMode(mRingerMode);
mGravitySensorFlg = false;
}
mTelephonyMgr.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_NONE);
mTsRes.unregOnSharedPrefChangeListener(this);
if (true == mTsRes.getOptTrayValue()) {
hideTrayIcon();
}
super.onDestroy();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPref,
String key) {
if (mTsRes.getOptTriggerDegreeKey().equals(key)) {
mTriggerDegree = getTriggerDegree();
if (true == mTsRes.getOptTrayValue()) {
showTrayIcon();
}
} else if (mTsRes.getOptTrayKey().equals(key)) {
if (true == mTsRes.getOptTrayValue()) {
showTrayIcon();
} else {
hideTrayIcon();
}
}
}
private double getTriggerDegree() {
double degreeDbl;
String degreeStr = mTsRes.getOptTriggerDegreeValue();
degreeDbl = Double.parseDouble(degreeStr);
degreeDbl = degreeDbl * Math.PI / TurnSilenceUtility.DEGREE_PI;
degreeDbl = Math.sin(degreeDbl);
degreeDbl = degreeDbl * TurnSilenceUtility.GRAVITY;
return degreeDbl;
}
private void showTrayIcon() {
int trayIconID = 0;
String tickerText = null;
long when = 0L;
Notification notification;
String trayNotificationTitle;
String trayNotificationFormat;
String trayNotificationText;
Intent trayNotificationIntent;
PendingIntent trayNotificationPendingIntent;
double degreeDbl = 0;
String degreeStr = null;
trayNotificationTitle = mTsRes.getOptTrayNotificationTitle();
trayNotificationFormat = mTsRes.getOptTrayNotificationFormat();
degreeStr = mTsRes.getOptTriggerDegreeValue();
degreeDbl = Double.parseDouble(degreeStr);
trayNotificationText = String.format(trayNotificationFormat, degreeDbl);
trayNotificationIntent = new Intent(this, mMainClass);
trayNotificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
trayNotificationPendingIntent = PendingIntent.getActivity(this,
TurnSilenceUtility.NOTIFICATION_ID_TRAY,
trayNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
trayIconID = mTsRes.getTrayIconId();
tickerText = mTsRes.getOptTrayTickerText();
when = System.currentTimeMillis();
notification = new Notification(trayIconID, tickerText, when);
notification.flags = Notification.FLAG_ONGOING_EVENT;
notification.setLatestEventInfo(this, trayNotificationTitle,
trayNotificationText, trayNotificationPendingIntent);
mNotificationMgr.notify(TurnSilenceUtility.NOTIFICATION_ID_TRAY,
notification);
return;
}
private void hideTrayIcon() {
mNotificationMgr.cancel(TurnSilenceUtility.NOTIFICATION_ID_TRAY);
return;
}
}TurnSilenceAbout.java
public class TurnSilenceAbout extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about);
}
}TurnSilenceUtility.java
public class TurnSilenceUtility {
public static final double GRAVITY = 9.81;
public static final double DEGREE_PI = 180;
public static final int NOTIFICATION_ID_TRAY = 0;
public static void startService(TurnSilenceResource tsRes, Class<?> destCls,
Class<?> mainCls) {
Context context;
String str = null;
Intent i;
context = tsRes.getAppContext();
i = new Intent(context, destCls);
str = mainCls.getCanonicalName();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(tsRes.getDataMainClassKey(), str);
context.startService(i);
}
public static void stopService(TurnSilenceResource tsRes, Class<?> destCls) {
Context context;
Intent i;
context = tsRes.getAppContext();
i = new Intent(context, destCls);
context.stopService(i);
}
}TurnSilenceResource.java
public class TurnSilenceResource {
private Context mAppContext;
private SharedPreferences mSharedPref;
private String mOptCallKey = null;
private boolean mOptCallDefaultValue = false;
private String mOptRealDegreeKey = null;
private String mOptRealDegreeFormat = null;
private String mOptTriggerDegreeKey = null;
private String mOptTriggerDegreeDefaultValue = null;
private String mOptTrayKey = null;
private boolean mOptTrayDefaultValue = false;
private String mOptTrayTickerText = null;
private String mOptTrayNotificationTitle = null;
private String mOptTrayNotificationFormat = null;
private String mDataMainClassKey = null;
private int mTrayIcon = 0;
public TurnSilenceResource(Context context) {
getStringValue(context);
getResId();
mSharedPref = PreferenceManager.getDefaultSharedPreferences(context);
mAppContext = context;
}
public String getOptCallKey() {
return mOptCallKey;
}
public String getOptRealDegreeKey() {
return mOptRealDegreeKey;
}
public String getOptRealDegreeFormat() {
return mOptRealDegreeFormat;
}
public String getOptTriggerDegreeKey() {
return mOptTriggerDegreeKey;
}
public String getOptTrayKey() {
return mOptTrayKey;
}
public String getOptTrayTickerText() {
return mOptTrayTickerText;
}
public String getOptTrayNotificationTitle() {
return mOptTrayNotificationTitle;
}
public String getOptTrayNotificationFormat() {
return mOptTrayNotificationFormat;
}
public String getDataMainClassKey() {
return mDataMainClassKey;
}
public Context getAppContext() {
return mAppContext;
}
public int getTrayIconId() {
return mTrayIcon;
}
public boolean getOptCallValue() {
return mSharedPref.getBoolean(mOptCallKey, mOptCallDefaultValue);
}
public String getOptTriggerDegreeValue() {
return mSharedPref.getString(mOptTriggerDegreeKey,
mOptTriggerDegreeDefaultValue);
}
public boolean getOptTrayValue() {
return mSharedPref.getBoolean(mOptTrayKey, mOptTrayDefaultValue);
}
public void regOnSharedPrefChangeListener(
OnSharedPreferenceChangeListener listener) {
mSharedPref.registerOnSharedPreferenceChangeListener(listener);
}
public void unregOnSharedPrefChangeListener(
OnSharedPreferenceChangeListener listener) {
mSharedPref.unregisterOnSharedPreferenceChangeListener(listener);
}
private void getStringValue(Context context) {
String str = null;
mOptCallKey = context.getResources().getString(R.string.opt_call_key);
str = context.getResources().getString(R.string.opt_call_default_value);
mOptCallDefaultValue = Boolean.valueOf(str);
mOptRealDegreeKey = context.getResources().getString(
R.string.opt_real_degree_key);
mOptTriggerDegreeKey = context.getResources().getString(
R.string.opt_trigger_degree_key);
mOptTriggerDegreeDefaultValue = context.getResources().getString(
R.string.opt_trigger_degree_default_value);
mOptRealDegreeFormat = context.getResources().getString(
R.string.opt_real_degree_format);
mOptTrayKey = context.getResources().getString(R.string.opt_tray_key);
mOptTrayDefaultValue = false;
str = context.getResources().getString(R.string.opt_tray_default_value);
mOptTrayDefaultValue = Boolean.valueOf(str);
mOptTrayTickerText = context.getResources().getString(
R.string.opt_tray_ticker_text);
mOptTrayNotificationTitle = context.getResources().getString(
R.string.opt_tray_notification_title);
mOptTrayNotificationFormat = context.getResources().getString(
R.string.opt_tray_notification_title);
mOptTrayNotificationFormat = context.getResources().getString(
R.string.opt_tray_notification_format);
mDataMainClassKey = context.getResources().getString(
R.string.data_main_class_key);
}
private void getResId() {
mTrayIcon = R.drawable.icon;
}
}res/layout/option.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference android:key="@string/opt_call_key"
android:title="@string/opt_call_title" android:summary="@string/opt_call_summary"
android:defaultValue="@string/opt_call_default_value" />
<Preference android:key="@string/opt_real_degree_key"
android:title="@string/opt_real_degree_title" android:summary="@string/opt_real_degree_summary" />
<EditTextPreference android:key="@string/opt_trigger_degree_key"
android:title="@string/opt_trigger_degree_title" android:summary="@string/opt_trigger_degree_summary"
android:dialogTitle="@string/opt_trigger_degree_dialogtitle"
android:defaultValue="@string/opt_trigger_degree_default_value"
android:inputType="numberSigned|numberDecimal" />
<CheckBoxPreference android:key="@string/opt_tray_key"
android:title="@string/opt_tray_title" android:summary="@string/opt_tray_summary"
android:defaultValue="@string/opt_tray_default_value" />
</PreferenceScreen> res/layout/about.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:padding="10dip">
<TextView android:id="@+id/about_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/about_text" />
</ScrollView> res/menu/menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/item_about" android:title="@string/item_about_label"
android:alphabeticShortcut="@string/item_about_shortcut" />
<item android:id="@+id/item_exit" android:title="@string/item_exit_label"
android:alphabeticShortcut="@string/item_exit_shortcut" />
</menu> res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, TurnSilence!</string>
<string name="app_name">翻转静音</string>
<string name="opt_call_key">opt_call</string>
<string name="opt_call_title">电话</string>
<string name="opt_call_summary">来电时进行翻转静音</string>
<string name="opt_call_default_value">true</string>
<string name="opt_real_degree_key">opt_real_degree</string>
<string name="opt_real_degree_title">当前手机角度</string>
<string name="opt_real_degree_summary">设置翻转触发角度</string>
<string name="opt_real_degree_format">点击设置翻转触发角度为:%1$.0f°</string>
<string name="opt_trigger_degree_key">opt_trigger_degree</string>
<string name="opt_trigger_degree_title">翻转触发角度</string>
<string name="opt_trigger_degree_dialogtitle">输入角度</string>
<string name="opt_trigger_degree_summary">指定翻转触发角度</string>
<string name="opt_trigger_degree_default_value">-60</string>
<string name="opt_tray_key">opt_tray_key</string>
<string name="opt_tray_title">托盘图标</string>
<string name="opt_tray_summary">服务时显示托盘图标</string>
<string name="opt_tray_default_value">true</string>
<string name="item_about_label">关于</string>
<string name="item_about_shortcut">a</string>
<string name="item_exit_label">退出</string>
<string name="item_exit_shortcut">x</string>
<string name="about_title">About</string>
<string name="about_text">
送给我的朋友;)
</string>
<string name="opt_tray_ticker_text">翻转静音启动!</string>
<string name="opt_tray_notification_title">翻转静音</string>
<string name="opt_tray_notification_format">触发角度为:%1$.0f°</string>
<string name="data_main_class_key">data_main_class_key</string>
</resources> AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mtyy110.android.turnsilence" android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name=".TurnSilenceReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<service android:name=".TurnSilenceService">
</service>
<activity android:name=".TurnSilenceActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TurnSilenceAbout" android:label="@string/about_title"
android:theme="@android:style/Theme.Dialog">
</activity>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
更多阅读
双系统如何正确删除一个不想要的系统实现单系统 双系统安装教程
双系统如何正确删除一个不想要的系统实现单系统——简介双系统如何正确删除一个不想要的系统实现单系统。我们知道我不想使用双系统了我们传统的做法是直接格式化系统所在盘符,但是存在一个问题,就是我们格式化完,我们开机时还是会显示
细致完整的Android开发环境搭建教程 android源码环境搭建
??????? 相信学习Android开发的程序猿们都晓得,?首先就是android开发环境搭建。这一课说起来简单,但是对不少Android开发入门的小白来说还是一个难点,在安卓环境搭建过程中会遇到各种各样的问题,今天就来为大家汇总归纳关于android
2014省外语年会1 提高英语教与学的效果实现成绩与能力双赢 如何提高外语口语
提高英语教与学的效果 实现成绩与能力双赢---程晓堂一、为什么谈这个话题?1.就英语教学而言,高分低能现象普遍存在。2.应试教育可以提高考试成绩,但不利于提高实际语言运用能力,不利于学生的长远发展。3.最要求考试成绩无可厚非,但
完整的Android开发环境Eclipse+ADT+SDK(22.0.1) eclipse adt sdk 一套
现在开始学习Android嵌入式编程,首要的问题就是在Windows中搭建开发环境,就这个都要摸索很长的时间,总是在版本之间折腾折腾去,而且Google的Android正式差劲得很,经常是连不上,要不就是服务器改变了路径。把我收集的完整的搭建好的分享给
基于FPGA IP核的FFT实现 altera fft ip核
基于FPGA IP核的FFT实现(1/1)0 引 言数字信号处理数字信号处理数字信号处理就是用数值计算方法对数字序列进行各种处理,把信号变换成符合需要的某种形式。理论基础,其中最主要的是离散时间信号和离散时间系统理论以及一些数学理论。领