android L平臺增加來電翻轉靜音菜單、功能

</pre><pre code_snippet_id="1619352" snippet_file_name="blog_20160322_2_8772511" name="code" class="java">diff --git a/device/xxx/system.prop b/device/xxx/system.prop
index d93eeec..df31144 100755
--- a/device/xxx/system.prop
+++ b/device/xxx/system.prop
@@ -66,10 +66,12 @@ ro.kernel.zio=38,108,105,16
 debug.hwui.render_dirty_regions=false
 
 ro.sf.lcd_density=240
+ro.support.flipmute=true
 
diff --git a/frameworks/base/api/current.txt b/frameworks/base/api/current.txt
index 144f292..2c4ea43 100644
--- a/frameworks/base/api/current.txt
+++ b/frameworks/base/api/current.txt
@@ -14123,6 +14123,8 @@ package android.media {
     field public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8
     field public static final int FLAG_SHOW_UI = 1; // 0x1
     field public static final int FLAG_VIBRATE = 16; // 0x10
+    field public static final int FLIPMUTE_SETTING_OFF = 0; // 0x0
+    field public static final int FLIPMUTE_SETTING_ON = 1; // 0x1
     field public static final int FX_FOCUS_NAVIGATION_DOWN = 2; // 0x2
     field public static final int FX_FOCUS_NAVIGATION_LEFT = 3; // 0x3
     field public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; // 0x4
@@ -25439,6 +25441,7 @@ package android.provider {
     field public static final deprecated java.lang.String DIM_SCREEN = "dim_screen";
     field public static final java.lang.String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
     field public static final java.lang.String END_BUTTON_BEHAVIOR = "end_button_behavior";
+    field public static final java.lang.String FLIPMUTE_WHEN_RINGING = "flipmute_when_ringing";
     field public static final java.lang.String FONT_SCALE = "font_scale";
     field public static final java.lang.String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
diff --git a/frameworks/base/api/system-current.txt b/frameworks/base/api/system-current.txt
index ca783e1..174e758 100644
--- a/frameworks/base/api/system-current.txt
+++ b/frameworks/base/api/system-current.txt
@@ -15146,6 +15146,8 @@ package android.media {
     field public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8
     field public static final int FLAG_SHOW_UI = 1; // 0x1
     field public static final int FLAG_VIBRATE = 16; // 0x10
+    field public static final int FLIPMUTE_SETTING_OFF = 0; // 0x0
+    field public static final int FLIPMUTE_SETTING_ON = 1; // 0x1
     field public static final int FX_FOCUS_NAVIGATION_DOWN = 2; // 0x2
     field public static final int FX_FOCUS_NAVIGATION_LEFT = 3; // 0x3
     field public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; // 0x4
@@ -27031,6 +27033,7 @@ package android.provider {
     field public static final deprecated java.lang.String DIM_SCREEN = "dim_screen";
     field public static final java.lang.String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
     field public static final java.lang.String END_BUTTON_BEHAVIOR = "end_button_behavior";
+    field public static final java.lang.String FLIPMUTE_WHEN_RINGING = "flipmute_when_ringing";
     field public static final java.lang.String FONT_SCALE = "font_scale";
     field public static final java.lang.String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
diff --git a/frameworks/base/core/java/android/provider/Settings.java b/frameworks/base/core/java/android/provider/Settings.java
index f97d9e8..576c1f4 100644
--- a/frameworks/base/core/java/android/provider/Settings.java
+++ b/frameworks/base/core/java/android/provider/Settings.java
@@ -2414,6 +2414,15 @@ public final class Settings {
          */
         public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
 
+
+	//jimbo add  start
+    /**
+     * Flip mute setting when incall ringing
+     *	
+     */
+        public static final String FLIPMUTE_WHEN_RINGING = "flipmute_when_ringing";
+    //jimbo add end
+
         /**
          * Whether the audible DTMF tones are played by the dialer when dialing. The value is
          * boolean (1 or 0).
@@ -2739,6 +2748,7 @@ public final class Settings {
             SIP_RECEIVE_CALLS,
             POINTER_SPEED,
             VIBRATE_WHEN_RINGING,
+            FLIPMUTE_WHEN_RINGING,	//jimbo add
             RINGTONE,
             LOCK_TO_APP_ENABLED,
             NOTIFICATION_SOUND,
diff --git a/frameworks/base/media/java/android/media/AudioManager.java b/frameworks/base/media/java/android/media/AudioManager.java
index dff5d51..ae1b607 100644
--- a/frameworks/base/media/java/android/media/AudioManager.java
+++ b/frameworks/base/media/java/android/media/AudioManager.java
@@ -631,6 +631,15 @@ public class AudioManager {
      */
     public static final int VIBRATE_SETTING_ON = 1;
 
+	//jimbo add  start
+    /**
+     * Flip mute setting when incall ringing
+     *	
+     */
+    public static final int FLIPMUTE_SETTING_OFF = 0;	
+    public static final int FLIPMUTE_SETTING_ON = 1;
+    //jimbo add end
+    
     /**
      * Vibrate setting that suggests to only vibrate when in the vibrate ringer
      * mode.
diff --git a/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index c9e1e42..4073e22 100644
--- a/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1107,6 +1107,11 @@ public class DatabaseHelper extends SQLiteOpenHelper {
         if (upgradeVersion == 77) {
             // Introduce "vibrate when ringing" setting
             loadVibrateWhenRingingSetting(db);
+	      //jimbo add for flip_mute start 
+	      if (SystemProperties.getBoolean("ro.support.flipmute", false)) {  
+			loadFlipMuteWhenRingingSetting(db);
+	      	}
+		//jimbo add end
 
             upgradeVersion = 78;
         }
@@ -2259,6 +2264,12 @@ public class DatabaseHelper extends SQLiteOpenHelper {
         }
 
         loadVibrateWhenRingingSetting(db);
+
+      //jimbo add for flip_mute start 
+      if (SystemProperties.getBoolean("ro.support.flipmute", false)) {  
+		loadFlipMuteWhenRingingSetting(db);
+      	}
+	//jimbo add end
     }
 
     private void loadVibrateSetting(SQLiteDatabase db, boolean deleteOld) {
@@ -2303,6 +2314,21 @@ public class DatabaseHelper extends SQLiteOpenHelper {
             if (stmt != null) stmt.close();
         }
     }
+	
+      //jimbo add for flip_mute start 
+    private void loadFlipMuteWhenRingingSetting(SQLiteDatabase db) {
+        int flipMuteWhenRinging = getIntValueFromSystem(db, Settings.System.FLIPMUTE_WHEN_RINGING, AudioManager.FLIPMUTE_SETTING_ON);
+			
+        SQLiteStatement stmt = null;
+        try {
+            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+                    + " VALUES(?,?);");
+            loadSetting(stmt, Settings.System.FLIPMUTE_WHEN_RINGING, flipMuteWhenRinging);
+        } finally {
+            if (stmt != null) stmt.close();
+        }
+    }
+//jimbo add end
 
     private void loadSettings(SQLiteDatabase db) {
 
diff --git a/packages/apps/Dialer/AndroidManifest.xml b/packages/apps/Dialer/AndroidManifest.xml
index 8f15d4c..9d1f9e3 100644
--- a/packages/apps/Dialer/AndroidManifest.xml
+++ b/packages/apps/Dialer/AndroidManifest.xml
@@ -288,6 +288,9 @@
                   android:exported="false"
                   android:screenOrientation="nosensor" >
         </activity>
+        
+        <service android:name="com.android.incallui.SensorFunctionServiceIncall"
+        		android:exported="false" />
 
         <activity android:name="com.android.incallui.CircularRevealActivity"
                   android:theme="@style/Theme.CircularRevealAnimation"
@@ -376,5 +379,6 @@
                 <action android:name="com.android.incallui.ACTION_UPDATE_UI_FORCED" />
             </intent-filter>
         </receiver>
+
     </application>
 </manifest>
diff --git a/packages/apps/Dialer/persistent/AndroidManifest.xml b/packages/apps/Dialer/persistent/AndroidManifest.xml
index 4d2416f..37eca6b 100644
--- a/packages/apps/Dialer/persistent/AndroidManifest.xml
+++ b/packages/apps/Dialer/persistent/AndroidManifest.xml
@@ -289,6 +289,8 @@
                   android:exported="false"
                   android:screenOrientation="nosensor" >
         </activity>
+        <service android:name="com.android.incallui.SensorFunctionServiceIncall"
+        		android:exported="false" />
 
         <activity android:name="com.android.incallui.CircularRevealActivity"
                   android:theme="@style/Theme.CircularRevealAnimation"
diff --git a/packages/apps/Dialer/res/values-zh-rCN/strings.xml b/packages/apps/Dialer/res/values-zh-rCN/strings.xml
index da7d666..d6d58d0 100644
--- a/packages/apps/Dialer/res/values-zh-rCN/strings.xml
+++ b/packages/apps/Dialer/res/values-zh-rCN/strings.xml
@@ -183,6 +183,7 @@
     <string name="sounds_and_vibrate_category_title" msgid="7589787045192519254">"提示音和振動"</string>
     <string name="ringtone_title" msgid="760362035635084653">"手機鈴聲"</string>
     <string name="vibrate_on_ring_title" msgid="3362916460327555241">"有來電時響鈴並振動"</string>
+	<string name="flipmute_on_ring_title" >"有來電時翻轉靜音"</string>
     <string name="dtmf_tone_enable_title" msgid="6571449695997521615">"撥號鍵盤提示音"</string>
     <string name="other_settings_title" msgid="7976283601445863248">"其他"</string>
     <string name="respond_via_sms_setting_title" msgid="1318281521087951580">"快速回復"</string>
diff --git a/packages/apps/Dialer/res/values/strings.xml b/packages/apps/Dialer/res/values/strings.xml
index f6da415..14d7389 100644
--- a/packages/apps/Dialer/res/values/strings.xml
+++ b/packages/apps/Dialer/res/values/strings.xml
@@ -707,6 +707,7 @@
     <!-- Setting option name to enable or disable vibration when ringing the phone.
          [CHAR LIMIT=30] -->
     <string name="vibrate_on_ring_title">"Also vibrate for calls</string>
+	<string name="flipmute_on_ring_title">"Also flipmute for calls</string>
 
     <!-- Setting option name to enable or disable DTMF tone sound [CHAR LIMIT=30] -->
     <string name="dtmf_tone_enable_title">Dialpad tones</string>
diff --git a/packages/apps/Dialer/res/xml/general_settings.xml b/packages/apps/Dialer/res/xml/general_settings.xml
index b1a78c1..38cc1c9 100644
--- a/packages/apps/Dialer/res/xml/general_settings.xml
+++ b/packages/apps/Dialer/res/xml/general_settings.xml
@@ -58,6 +58,12 @@
             android:title="@string/vibrate_on_ring_title"
             android:persistent="false"
             android:defaultValue="false" />
+            
+       <!-- Also flipmute for calls -->
+        <CheckBoxPreference
+                android:key="button_flipmute_on_ringing"
+                android:title="@string/flipmute_on_ring_title"
+                android:persistent="false" />
 
     </PreferenceCategory>
 
@@ -80,4 +86,4 @@
 
     </PreferenceCategory>
 
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/packages/apps/Dialer/src/com/android/dialer/settings/GeneralSettingsFragment.java b/packages/apps/Dialer/src/com/android/dialer/settings/GeneralSettingsFragment.java
index d8354ef..979af68 100644
--- a/packages/apps/Dialer/src/com/android/dialer/settings/GeneralSettingsFragment.java
+++ b/packages/apps/Dialer/src/com/android/dialer/settings/GeneralSettingsFragment.java
@@ -67,6 +67,9 @@ public class GeneralSettingsFragment extends PreferenceFragment
     private CheckBoxPreference mVibrateWhenRinging;
     private CheckBoxPreference mPlayDtmfTone;
     private Preference mRespondViaSms;
+	
+    private static final String BUTTON_FLIPMUTE_ON_RING = "button_flipmute_on_ringing";//jimbo add
+    private CheckBoxPreference mFlipMuteWhenRinging;//jimbo add
 
     private Runnable mRingtoneLookupRunnable;
     private final Handler mRingtoneLookupComplete = new Handler() {
@@ -138,6 +141,25 @@ public class GeneralSettingsFragment extends PreferenceFragment
             }
         }
 
+//jimbo add start for flipmute
+	  mFlipMuteWhenRinging = (CheckBoxPreference) findPreference(BUTTON_FLIPMUTE_ON_RING);
+        if (mFlipMuteWhenRinging != null) {
+           if (android.os.SystemProperties.getBoolean("ro.support.flipmute", false)) {  
+			boolean bFlipMuteEnabled = Settings.System.getInt(getActivity().getContentResolver(), Settings.System.FLIPMUTE_WHEN_RINGING, 0) != 0;  
+			if (bFlipMuteEnabled != mFlipMuteWhenRinging.isChecked()) {
+				mFlipMuteWhenRinging.setChecked(bFlipMuteEnabled);
+			}
+
+			// click event
+			mFlipMuteWhenRinging.setOnPreferenceChangeListener(this);
+            } else {
+            		// hide
+                soundCategory.removePreference(mFlipMuteWhenRinging);
+                mFlipMuteWhenRinging = null;
+            }
+        }
+//jimbo add end
+
         if (mPlayDtmfTone != null) {
             mPlayDtmfTone.setOnPreferenceChangeListener(this);
             /// M: [ALPS01841736] add listener for DMTF change
@@ -175,6 +197,12 @@ public class GeneralSettingsFragment extends PreferenceFragment
             /// M: [ALPS01791893] phone not vibrate, when the MT call
             setVibrateOnRing(doVibrate);
         }
+	//jimbo add start for flipmute
+	else if(preference == mFlipMuteWhenRinging){
+            boolean enable = (Boolean) objValue;
+		Settings.System.putInt(mContext.getContentResolver(), Settings.System.FLIPMUTE_WHEN_RINGING, enable ? 1 : 0);
+	}
+	//jimbo add end
         return true;
     }
 
diff --git a/packages/apps/InCallUI/src/com/android/incallui/InCallActivity.java b/packages/apps/InCallUI/src/com/android/incallui/InCallActivity.java
index 3087b3c..a947462 100644
--- a/packages/apps/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/packages/apps/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -52,6 +52,10 @@ import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 
+//jimbo add for flip_mute start 
+import android.provider.Settings;
+//jimbo add end
+
 import com.android.ims.ImsManager;
 import com.android.phone.common.animation.AnimUtils;
 import com.android.phone.common.animation.AnimationListenerAdapter;
@@ -251,7 +255,7 @@ public class InCallActivity extends Activity {
         }
         super.onSaveInstanceState(out);
     }
-
+	
     @Override
     protected void onStart() {
         Log.d(this, "onStart()...");
@@ -259,6 +263,19 @@ public class InCallActivity extends Activity {
 
         // setting activity should be last thing in setup process
         InCallPresenter.getInstance().setActivity(this);
+		
+//jimbo add for flip_mute start 
+      if (android.os.SystemProperties.getBoolean("ro.support.flipmute", false)) {  
+		final boolean bFlipMuteEnabled = Settings.System.getInt(getContentResolver(), Settings.System.FLIPMUTE_WHEN_RINGING, 0) != 0;  
+
+		if (bFlipMuteEnabled) {
+			final Intent intent = new Intent(this, SensorFunctionServiceIncall.class);  
+			//intent.setAction("com.android.incallui.SensorFunctionServiceIncall");  
+			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+			this.startService(intent);  
+		}  
+	}  
+//jimbo add end		
     }
 
     @Override
@@ -351,6 +368,19 @@ public class InCallActivity extends Activity {
         mAnimateDialpadOnShow = false;
         mDtmfText = null;
         /// @}
+
+//jimbo add for flip_mute start 
+      if (android.os.SystemProperties.getBoolean("ro.support.flipmute", false)) {  
+		final boolean bFlipMuteEnabled = Settings.System.getInt(getContentResolver(), Settings.System.FLIPMUTE_WHEN_RINGING, 0) != 0;  
+
+		if (bFlipMuteEnabled) {  
+			final Intent intent = new Intent(this, SensorFunctionServiceIncall.class);  
+			//intent.setAction("com.android.incallui.SensorFunctionServiceIncall");  
+			this.stopService(intent);  
+		}  
+	}  
+//jimbo add end		
+		
         super.onStop();
     }
 
diff --git a/packages/apps/InCallUI/src/com/android/incallui/SensorFunctionServiceIncall.java b/packages/apps/InCallUI/src/com/android/incallui/SensorFunctionServiceIncall.java
new file mode 100644
index 0000000..21e4e13
--- /dev/null
+++ b/packages/apps/InCallUI/src/com/android/incallui/SensorFunctionServiceIncall.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui;
+
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.media.AudioManager;
+import android.util.Log;
+import android.content.BroadcastReceiver;
+
+public class SensorFunctionServiceIncall extends Service {
+
+	private static final String LOG_TAG = "InCallActivity/SensorFunctionServiceIncall";
+	private static final float CRITICAL_DOWN_ANGLE = -5.0f;
+	private static final float CRITICAL_UP_ANGLE = 5.0f;
+	private static final int Z_ORATIATION = 2;
+
+	private SensorManager mSensorManager;
+	private Sensor mGsensor;
+	private SensorEventListener mGsensorListener;
+	private int mReverseDownFlg = -1;
+	private int previousMuteMode = -1;
+
+
+
+	private boolean mActFlag = false;
+
+	@Override
+	public void onCreate() {
+		super.onCreate();
+
+		mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
+		mGsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);// TYPE_GRAVITY);
+
+		Log.d(LOG_TAG, "onCreate()...  this = " + this);
+
+		mGsensorListener = new SensorEventListener() {
+
+			@Override
+			public void onAccuracyChanged(Sensor sensor, int accuracy) {
+			}
+
+			@Override
+			public void onSensorChanged(SensorEvent event) {
+				//Log.d(LOG_TAG,"onSensorChanged()...  event.values[SensorManager.DATA_Z] = " + event.values[SensorManager.DATA_Z]);
+
+				if (event.values[SensorManager.DATA_Z] >= CRITICAL_UP_ANGLE) { // screen up first
+					mReverseDownFlg = 0;
+				} else if (event.values[SensorManager.DATA_Z] <= CRITICAL_DOWN_ANGLE
+							&& mReverseDownFlg == 0) { // screen down next
+					mReverseDownFlg = 1;
+				}
+				//Log.d(LOG_TAG,"onSensorChanged()..............  mReverseDownFlg = " + mReverseDownFlg+"  previousMuteMode="+previousMuteMode);
+
+				if (mReverseDownFlg == 1) { // screen reverse from up to down
+					AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+					if (previousMuteMode == -1 && am != null) {
+						previousMuteMode = am.getRingerMode();
+						am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+						
+						Log.d(LOG_TAG,"onSensorChanged()..............  set mute----------------- ");
+					}
+					/*else{
+						am.setRingerMode(previousMuteMode);
+						previousMuteMode = -1;
+					}*/
+				}
+			}
+		};
+
+		if(mGsensorListener != null && mGsensor != null){
+			mSensorManager.registerListener(mGsensorListener, mGsensor,	SensorManager.SENSOR_DELAY_GAME);
+		}
+	}
+
+	@Override
+	public IBinder onBind(Intent arg0) {
+		return null;
+	}
+
+	@Override
+	public void onDestroy() {
+		AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+		if (previousMuteMode != -1 && am != null) {
+			am.setRingerMode(previousMuteMode);
+			previousMuteMode = -1;
+			
+			Log.d(LOG_TAG,"onDestroy()..............  set noraml----------------- ");
+		}
+	
+		if(mGsensorListener != null && mGsensor != null){
+			mSensorManager.unregisterListener(mGsensorListener, mGsensor);
+		}
+	}
+
+}


以下是其他方法:

轉自:http://www.android100.org/html/201409/10/64057.html


在CallNotifier.java中 加入如下代碼:


        public void flipMute(Context contextg) {  
            sm = (SensorManager)getSystemService(Service.SENSOR_SERVICE);  
            sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
            mySensorListener = new SensorEventListener() {  
                @Override  
                public void onSensorChanged(SensorEvent event) {  
                    x = event.values[0];   
                    y = event.values[1];   
                    z = event.values[2];  
      
                    if (x < 1 && x > -1 && y < 1 && y > -1) {  
                      
                        if (z > 0) {  
                            mGoUp = true;  
                              
                        } else {  
                              
                            mGoUp = false;  
                        }  
                          
                    } else {  
    //                  if (x > 1 || x < -1 || y > 1 || y < -1 ) {  
                              
                            if ( z > 0 && !mGoUp ) {  
                                mRinger.stopRing();  
                                if(mySensorListener != null){  
                                    sm.unregisterListener(mySensorListener);    //Add by kylin 2013.07.25  
                                      
                                }  
                            }   
                            if ( z < 0 && mGoUp ) {  
                                mRinger.stopRing();  
                                if(mySensorListener != null){  
                                    sm.unregisterListener(mySensorListener);    //Add by kylin 2013.07.25  
                                }  
                            }   
      
      
    //                  }   
                          
                    }  
                      
                }  
      
      
                @Override  
                public void onAccuracyChanged(Sensor sensor, int accuracy) {  
                    // TODO Auto-generated method stub  
      
                }  
            };  
            sm.registerListener(mySensorListener, sensor,  
                    SensorManager.SENSOR_DELAY_GAME);  
              
        }  
再在相應位置調用如上方法即可以實現此功能。


android 重力感應監聽:
    public class ShakeListener implements SensorEventListener {  
        public static ShakeListener sensor1;  
        // 速度閾值,當搖晃速度達到這值後產生作用  
        private static final int SPEED_SHRESHOLD = 400;  
        // 兩次檢測的時間間隔  
        private static final int UPTATE_INTERVAL_TIME = 70;  
      
        // 傳感器管理器  
        private SensorManager sensorManager;  
        // 傳感器  
        private Sensor sensor;  
        // 重力感應監聽器  
        private OnShakeListener onShakeListener;  
        // 上下文  
        private static Context context;  
        // 手機上一個位置時重力感應座標  
        private float lastX;  
        private float lastY;  
        private float lastZ;  
      
        // 上次檢測時間  
        private long lastUpdateTime;  
      
      
          
      
        public static ShakeListener newInstance(Context c) {  
            if (sensor1 == null) {  
                sensor1 = new ShakeListener();  
                context = c;  
                return sensor1;  
            } else {  
                return sensor1;  
            }  
        }  
      
        // 開始  
        public void start() {  
            // 獲得傳感器管理器  
            if(sensorManager==null){  
                sensorManager = (SensorManager) context  
                .getSystemService(Context.SENSOR_SERVICE);    
            }  
            if (sensorManager != null&&sensor==null) {  
                // 獲得重力傳感器  
                sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
            }  
            if (sensor != null) {  
                sensorManager.registerListener(this, sensor,  
                        SensorManager.SENSOR_DELAY_NORMAL);  
            }  
        }  
      
      
      
        // 停止檢測  
        public void stop() {  
            sensorManager.unregisterListener(this);  
        }  
      
        // 搖晃監聽接口  
        public interface OnShakeListener {  
            public void onShake();  
        }  
      
        // 設置重力感應監聽器  
        public void setOnShakeListener(OnShakeListener listener) {  
            onShakeListener = listener;  
        }  
      
        // 重力感應器感應獲得變化數據  
        @Override  
        public void onSensorChanged(SensorEvent event) {  
      
            long currentUpdateTime = System.currentTimeMillis();  
            // 兩次檢測的時間間隔  
            long timeInterval = currentUpdateTime - lastUpdateTime;  
            // 判斷是否達到了檢測時間間隔  
            if (timeInterval < UPTATE_INTERVAL_TIME) {  
                return;  
            }  
            // 現在的時間變成last時間  
            lastUpdateTime = currentUpdateTime;  
      
            // 獲得x,y,z座標  
            float x = event.values[0];  
            float y = event.values[1];  
            float z = event.values[2];  
      
            // 獲得x,y,z的變化值  
            float deltaX = x - lastX;  
            float deltaY = y - lastY;  
            float deltaZ = z - lastZ;  
      
            // 將現在的座標變成last座標  
            lastX = x;  
            lastY = y;  
            lastZ = z;  
      
            double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ  
                    * deltaZ)  
                    / timeInterval * 10000;  
            // 達到速度閥值,發出提示  
            if (speed >= SPEED_SHRESHOLD){  
                // 手機晃動  
                onShakeListener.onShake();  
            }  
        }  
        public void onAccuracyChanged(Sensor sensor, int accuracy) {  
      
        }  
      
    }  



原理:監聽phone狀態,來電時啓動一個服務監聽Gsensor 當檢測到手機從向上翻轉到向下(Z值5以上翻到到-5以下),設置ringtone音量爲0  來電接通或掛斷後恢復ringtone音量

註冊phone狀態監聽器:本文選自com.android.systemui.statusbar.phone.PhoneStatusBar onStart函數最後

</pre><p></p><p></p><pre code_snippet_id="1619352" snippet_file_name="blog_20160322_4_9263662" name="code" class="java">public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener {

    public void start() {
    ......
//jimbo add for flip_mute start 
      if (android.os.SystemProperties.getBoolean("ro.flipmute.support", false)) {  
 Xlog.d("jimbo", "PhoneStatusBar-- start--- ");
		TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);  
	       telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);  
	}  
//jimbo add end		
    }

//jimbo add for flip_mute start 
    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
		
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {

		final Intent intent = new Intent(mContext, SensorFunctionServiceIncall.class);  
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		boolean bFlipMuteEnabled = Settings.System.getInt(mContext.getContentResolver(), Settings.System.FLIPMUTE_WHEN_RINGING, 0) != 0;  
            //Xlog.d("jimbo", "PhoneStateListener, new state=" + state+"   bFlipMuteEnabled="+bFlipMuteEnabled);
		
	        switch (state) {  
	            case TelephonyManager.CALL_STATE_IDLE:  
	                 //Xlog.d("jimbo", "PhoneStateListener---idle");  
				mContext.stopService(intent);  
	                break;  
	            case TelephonyManager.CALL_STATE_RINGING:  
	                 //Xlog.d("jimbo", "PhoneStateListener---incoming " + incomingNumber);
				if (bFlipMuteEnabled) {
			    		mContext.startService(intent);  
				}
	                break;  
	            case TelephonyManager.CALL_STATE_OFFHOOK:  
	                // Xlog.d("jimbo", "PhoneStateListener---in calling");  
				mContext.stopService(intent);  
	            default:  
	                break;  
	        }  
            super.onCallStateChanged(state, incomingNumber);
        }
    };
//jimbo add end		

sensor服務內容:

package com.android.systemui.statusbar.phone;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.os.PowerManager;
import android.media.AudioManager;
import android.util.Log;
import android.content.BroadcastReceiver;

public class SensorFunctionServiceIncall extends Service {

	private static final String LOG_TAG = "SensorFunctionServiceIncall";
	private static final float CRITICAL_DOWN_ANGLE = -5.0f;
	private static final float CRITICAL_UP_ANGLE = 5.0f;
	private static final int Z_ORATIATION = 2;
	
	private AudioManager mAudioManager;
	private SensorManager mSensorManager;
	private Sensor mGsensor;
	private SensorEventListener mGsensorListener;
	private int mReverseDownFlg = -1;
	private int previousMuteMode = -1;



	private boolean mActFlag = false;

	@Override
	public void onCreate() {
		super.onCreate();

		mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		mGsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);// TYPE_GRAVITY);
		
		mAudioManager= (AudioManager) getSystemService(Context.AUDIO_SERVICE);

		Log.d(LOG_TAG, "onCreate()...  this = " + this);

		mGsensorListener = new SensorEventListener() {

			@Override
			public void onAccuracyChanged(Sensor sensor, int accuracy) {
			}

			@Override
			public void onSensorChanged(SensorEvent event) {
				//Log.d(LOG_TAG,"onSensorChanged()...  event.values[SensorManager.DATA_Z] = " + event.values[SensorManager.DATA_Z]);

				if (event.values[SensorManager.DATA_Z] >= CRITICAL_UP_ANGLE) { // screen up first
					mReverseDownFlg = 0;
				} else if (event.values[SensorManager.DATA_Z] <= CRITICAL_DOWN_ANGLE
							&& mReverseDownFlg == 0) { // screen down next
					mReverseDownFlg = 1;
				}
				//Log.d(LOG_TAG,"onSensorChanged()..............  mReverseDownFlg = " + mReverseDownFlg+"  previousMuteMode="+previousMuteMode);

				if (mReverseDownFlg == 1) { // screen reverse from up to down
					if (previousMuteMode == -1 && mAudioManager != null) {
						//previousMuteMode = mAudioManager.getRingerMode();
						//mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);

						previousMuteMode = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
						mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
						
						Log.d(LOG_TAG,"onSensorChanged().........mute.....  previousMuteMode="+previousMuteMode);
					}
				}
			}
		};

		if(mGsensorListener != null && mGsensor != null){
			mSensorManager.registerListener(mGsensorListener, mGsensor,	SensorManager.SENSOR_DELAY_GAME);
		}
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public void onDestroy() {
		if (previousMuteMode != -1 && mAudioManager != null) {
			//mAudioManager.setRingerMode(previousMuteMode);
			mAudioManager.setStreamVolume(AudioManager.STREAM_RING, previousMuteMode, 0);
			previousMuteMode = -1;
			
			Log.d(LOG_TAG,"onDestroy()..............  set noraml----------------- ");
		}
	
		if(mGsensorListener != null && mGsensor != null){
			mSensorManager.unregisterListener(mGsensorListener, mGsensor);
		}
	}

}




發佈了37 篇原創文章 · 獲贊 22 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章