您的位置:首页 > 移动开发 > Android开发

Android 手势控制解锁,滑动图片,照相,音乐切换,收音机换台,短信界面打电话

2015-12-03 21:18 1576 查看
我的android版本是5.1的

我想要实现的是在设置里面有很多开关对应这些功能是否开放,并且有一个总开关来控制

默认都是关闭的效果。

我要说的是,我是通过距离传感器来实现这些功能的,

智能手机里面有很多种传感器,距离传感器是其中的一种,

要实现想要的功能,我是通过以下几步来实现的。

首先------>

在Setings主界面最下面加上一项手势控制

这一项我是在dashboard_categories.xml里加的,dashboard_categories是主界面的布局

里面的每一项都是一个dashboard,有对应的id,title,fragment,icon,如下

<!-- Gesture induction -->
<dashboard-tile
android:id="@+id/gesture_induction"
android:title="@string/gesture_induction"
android:fragment="com.android.settings.GestureInductionSettings"
android:icon="@drawable/ic_settings_about"
/>
要想成功添加一项,这还远远不够,要在Strings.xml里面添加title的字符串

<string name="gesture_induction" product="default">Gesture Induction</string>
在Settings.java里面加上GestureInductionSettings继承SettingsActivity

在AndroidManifest.xml里配置这个activity,如下

<activity android:name="Settings$GestureInductionSettingsActivity"
android:theme="@style/Theme.SubSettingsDialogWhenLarge"
android:label="@string/device_info_settings"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.GESTURE_INDUCTION_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.GestureInductionSettings" />
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
android:resource="@id/gesture_induction" />
</activity>
在res的layout中添加gesture_induction_settings.xml布局文件,如下所示<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/gesture_induction">

<PreferenceCategory
android:title="@string/support_gesture_apps">

<SwitchPreference
android:key="camera_gesture"
android:title="@string/camera_gesture_title"
android:summary="@string/camera_gesture_summary"
android:persistent="false" />
<SwitchPreference
android:key="keyguard_gesture"
android:title="@string/keyguard_gesture_title"
android:summary="@string/keyguard_gesture_summary"
android:persistent="false" />
<SwitchPreference
android:key="gallery2_gesture"
android:title="@string/gallery2_gesture_title"
android:summary="@string/gallery2_gesture_summary"
android:persistent="false" />
<SwitchPreference
android:key="music_gesture"
android:title="@string/music_gesture_title"
android:summary="@string/music_gesture_summary"
android:persistent="false" />
<SwitchPreference
android:key="fm_gesture"
android:title="@string/fm_gesturee_title"
android:summary="@string/fm_gesture_summary"
android:persistent="false" />
</PreferenceCategory>

</PreferenceScreen>
然后就是编写这个activity的代码了
package com.android.settings;

import android.os.Bundle;
import android.preference.Preference;
import android.app.Activity;
import android.preference.SwitchPreference;
import android.content.Context;
import android.content.ContentResolver;
import android.provider.Settings;
import android.content.res.Configuration;
import android.util.Log;
import com.android.settings.widget.SwitchBar;
import java.util.ArrayList;
import android.widget.Switch;

import static android.provider.Settings.System.CAMERA_GESTURE_MODE;
import static android.provider.Settings.System.KEYGUARD_GESTURE_MODE;
import static android.provider.Settings.System.GALLERY_GESTURE_MODE;
import static android.provider.Settings.System.MUSIC_GESTURE_MODE;
import static android.provider.Settings.System.FM_GESTURE_MODE;
import static android.provider.Settings.Global.GESTURE_SETTINGS_ENABLED;

public class GestureInductionSettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener,SwitchBar.OnSwitchChangeListener{

private static final String KEY_CAMERA_GESTURE = "camera_gesture";
private static final String KEY_KEYGUARD_GESTURE = "keyguard_gesture";
private static final String KEY_GALLERY_GESTURE = "gallery2_gesture";
private static final String KEY_MUSIC_GESTURE = "music_gesture";
private static final String KEY_FM_GESTURE = "fm_gesture";

private SwitchPreference mCameraPreference;
private SwitchPreference mKeyguardPreference;
private SwitchPreference mGalleryPreference;
private SwitchPreference mMusicPreference;
private SwitchPreference mFMPreference;
private final Configuration mCurConfig = new Configuration();
private SwitchBar mSwitchBar;
private boolean mLastEnabledState;
private final ArrayList<SwitchPreference> mAllPrefs = new ArrayList<SwitchPreference>();

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
Log.i("SettingsQL GestureInductionSettings", "onCreate");
final Activity activity = getActivity();

addPreferencesFromResource(R.xml.gesture_induction_settings);
mCameraPreference = (SwitchPreference) findPreference(KEY_CAMERA_GESTURE);
mKeyguardPreference = (SwitchPreference) findPreference(KEY_KEYGUARD_GESTURE);
mGalleryPreference = (SwitchPreference) findPreference(KEY_GALLERY_GESTURE);
mMusicPreference = (SwitchPreference) findPreference(KEY_MUSIC_GESTURE);
mFMPreference = (SwitchPreference) findPreference(KEY_FM_GESTURE);

mAllPrefs.add(mCameraPreference);
mAllPrefs.add(mKeyguardPreference);
mAllPrefs.add(mGalleryPreference);
mAllPrefs.add(mMusicPreference);
mAllPrefs.add(mFMPreference);

mCameraPreference.setOnPreferenceChangeListener(this);
mKeyguardPreference.setOnPreferenceChangeListener(this);
mGalleryPreference.setOnPreferenceChangeListener(this);
mMusicPreference.setOnPreferenceChangeListener(this);
mFMPreference.setOnPreferenceChangeListener(this);
}

@Override
public void onResume() {
super.onResume();
Log.i("SettingsQL GestureInductionSettings", "onResume");
updateState();
mLastEnabledState = Settings.Global.getInt(getActivity().getContentResolver(),
Settings.Global.GESTURE_SETTINGS_ENABLED, 0) != 0;
Log.i("SettingsQL GestureInductionSettings", "onResume mLastEnabledState="+mLastEnabledState);
mSwitchBar.setChecked(mLastEnabledState);
mSwitchBar.show();
setPrefsEnabledState(mLastEnabledState);
}
private void setPrefsEnabledState(boolean enabled) {
for (int i = 0; i < mAllPrefs.size(); i++) {
SwitchPreference pref = mAllPrefs.get(i);
pref.setEnabled(enabled);
}
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (switchView != mSwitchBar.getSwitch()) {
return;
}
if (isChecked != mLastEnabledState) {
if (isChecked) {
Log.i("SettingsQL GestureInductionSettings", "onSwitchChanged isChecked");
Settings.Global.putInt(getActivity().getContentResolver(),
Settings.Global.GESTURE_SETTINGS_ENABLED, 1);
setPrefsEnabledState(isChecked);
mLastEnabledState = isChecked;
} else {
Log.i("SettingsQL GestureInductionSettings", "onSwitchChanged notChecked");
setGestureDisabled();
Settings.Global.putInt(getActivity().getContentResolver(),
Settings.Global.GESTURE_SETTINGS_ENABLED, 0);
mLastEnabledState = isChecked;
setPrefsEnabledState(isChecked);
}
}
}
private void setGestureDisabled(){
mCameraPreference.setChecked(false);
Settings.System.putInt(getContentResolver(), CAMERA_GESTURE_MODE,0);
mKeyguardPreference.setChecked(false);
Settings.System.putInt(getContentResolver(), KEYGUARD_GESTURE_MODE,0);
mGalleryPreference.setChecked(false);
Settings.System.putInt(getContentResolver(), GALLERY_GESTURE_MODE,0);
mMusicPreference.setChecked(false);
Settings.System.putInt(getContentResolver(), MUSIC_GESTURE_MODE,0);
mFMPreference.setChecked(false);
Settings.System.putInt(getContentResolver(), FM_GESTURE_MODE,0);
};
@Override
public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);
mCurConfig.updateFrom(newConfig);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

final SettingsActivity activity = (SettingsActivity) getActivity();

mSwitchBar = activity.getSwitchBar();
mSwitchBar.setEnabled(true);

mSwitchBar.addOnSwitchChangeListener(this);
}
private void updateState() {
Log.i("SettingsQL GestureInductionSettings", "updateState");
if (mCameraPreference != null) {
int cameraGestureMode = Settings.System.getInt(getContentResolver(),
CAMERA_GESTURE_MODE, 0);
mCameraPreference.setChecked(cameraGestureMode != 0);
}
if (mKeyguardPreference != null) {
int keyguardGestureMode = Settings.System.getInt(getContentResolver(),
KEYGUARD_GESTURE_MODE, 0);
mKeyguardPreference.setChecked(keyguardGestureMode != 0);
}
if (mGalleryPreference != null) {
int galleryGestureMode = Settings.System.getInt(getContentResolver(),
GALLERY_GESTURE_MODE, 0);
mGalleryPreference.setChecked(galleryGestureMode != 0);
}
if (mMusicPreference != null) {
int musicGestureMode = Settings.System.getInt(getContentResolver(),
MUSIC_GESTURE_MODE, 0);
Log.i("SettingsQL GestureInductionSettings", "updateState musicGestureMode="+musicGestureMode);
mMusicPreference.setChecked(musicGestureMode != 0);
}
if (mFMPreference != null) {
int fmGestureMode = Settings.System.getInt(getContentResolver(),
FM_GESTURE_MODE, 0);
mFMPreference.setChecked(fmGestureMode != 0);
}

}

@Override
public void onPause() {
super.onPause();
Log.i("SettingsQL GestureInductionSettings", "onPause");
}

@Override
public boolean onPreferenceChange(Preference preference, Object objValue) {
Log.i("SettingsQL GestureInductionSettings", "onPreferenceChange");
if (preference == mCameraPreference) {
boolean enable = (Boolean) objValue;
Settings.System.putInt(getContentResolver(), CAMERA_GESTURE_MODE,
enable ? 1 : 0);
}
if (preference == mKeyguardPreference) {
boolean enable = (Boolean) objValue;
Settings.System.putInt(getContentResolver(), KEYGUARD_GESTURE_MODE,
enable ? 1 : 0);
}
if (preference == mGalleryPreference) {
boolean enable = (Boolean) objValue;
Settings.System.putInt(getContentResolver(), GALLERY_GESTURE_MODE,
enable ? 1 : 0);
}
if (preference == mMusicPreference) {
boolean enable = (Boolean) objValue;
Settings.System.putInt(getContentResolver(), MUSIC_GESTURE_MODE,
enable ? 1 : 0);
}
if (preference == mFMPreference) {
boolean enable = (Boolean) objValue;
Settings.System.putInt(getContentResolver(), FM_GESTURE_MODE,
enable ? 1 : 0);
}
return true;
}

}
等下再来解释代码的含义。
至此,设置里面的编辑就算完成了。

然后------>

现在我要编写的是frameworks层的东西。

由于设置里面要将开关的值保存到数据库,所以肯定要用到

android.provider.Settings这个类以及SettingsProvider这个应用

在电量百分比这篇文章里我已经写了一些关于这两个东西的作用

点击打开链接

首先要在defaults.xml里面加入默认值。

<bool name="def_camera_gesture_mode">false</bool>
<bool name="def_keyguard_gesture_mode">false</bool>
<bool name="def_gallery_gesture_mode">false</bool>
<bool name="def_music_gesture_mode">false</bool>
<bool name="def_fm_gesture_mode">false</bool>
<bool name="def_gesture_settings_enabled">false</bool>

然后在android.provider.Settings.System中加入各个功能静态值
public static String CAMERA_GESTURE_MODE="camera_gesture_mode";
public static String KEYGUARD_GESTURE_MODE="keyguard_gesture_mode";
public static String GALLERY_GESTURE_MODE="gallery_gesture_mode";
public static String MUSIC_GESTURE_MODE="music_gesture_mode";
public static String FM_GESTURE_MODE="fm_gesture_mode";
然后在android.provider.Settings.Global中加入总开关的静态值
public static String GESTURE_SETTINGS_ENABLED="gesture_settings_enabled";

然后在DatabaseHelper中的loadSystemSettings中加入
loadBooleanSetting(stmt, Settings.System.CAMERA_GESTURE_MODE,
R.bool.def_camera_gesture_mode);
loadBooleanSetting(stmt, Settings.System.KEYGUARD_GESTURE_MODE,
R.bool.def_keyguard_gesture_mode);
loadBooleanSetting(stmt, Settings.System.GALLERY_GESTURE_MODE,
R.bool.def_gallery_gesture_mode);
loadBooleanSetting(stmt, Settings.System.MUSIC_GESTURE_MODE,
R.bool.def_music_gesture_mode);
loadBooleanSetting(stmt, Settings.System.FM_GESTURE_MODE,
R.bool.def_fm_gesture_mode);用来将各个开关的默认值写入数据库System中
然后在DatabaseHelper中的loadGlobalSettings中加入

loadBooleanSetting(stmt, Settings.Global.GESTURE_SETTINGS_ENABLED,
R.bool.def_gesture_settings_enabled);用来将总开关的默认值写入数据库Global中

最后------>

就是各个应用的编写了,我需要在各个应用中将数据库中的值取到,

然后用这个值来决定是否打开距离传感器来控制想要的功能

1》照相功能的实现:

找到CameraActivity,我把要加入的代码贴出来

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.provider.Settings;
import static android.provider.Settings.System.CAMERA_GESTURE_MODE;

//成员变量
private SensorManager sensorManager=null;
private Sensor proximitySensor=null;
private boolean mNeedSensorToWork=false;
private ProximitySensorEventListener mProximitySensorListener=null;
private int gestureValue;

//onCreate方法中添加
sensorManager =
(SensorManager)getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (proximitySensor == null) {
mProximitySensorListener = null;
} else {
mProximitySensorListener =
new ProximitySensorEventListener(sensorManager, proximitySensor);
}

//onResume方法中添加
gestureValue=Settings.System.getInt(getContentResolver(), CAMERA_GESTURE_MODE,0);
mNeedSensorToWork=gestureValue==1?true:false;
if(mNeedSensorToWork){

mProximitySensorListener.register();
}
//onPause方法中添加
mProximitySensorListener.unregister();

//监听和执行
public static enum State {
NEAR, FAR
}
private class ProximitySensorEventListener implements SensorEventListener{
private final SensorManager mSensorManager;
private final Sensor mProximitySensor;
private final float mMaxValue;

private State mLastState=State.FAR;

public ProximitySensorEventListener(SensorManager sensorManager, Sensor proximitySensor
) {
mSensorManager = sensorManager;
mProximitySensor=proximitySensor;
mMaxValue=proximitySensor.getMaximumRange();

}

@Override
public void onSensorChanged(SensorEvent event) {
float value=event.values[0];
State state=getStateFromValue(value);
if(state==State.NEAR&&mLastState==State.FAR){
mLastState=State.NEAR;
return;
}
if(state==State.FAR&&mLastState==State.NEAR){
Log.i("Gallery2QL", "onSensorChanged");
mCameraAppUi.getPhotoShutter().performClick();
mLastState=State.FAR;
}

}

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

}
/** Returns the state of the sensor given its current value. */
private State getStateFromValue(float value) {
return value==mMaxValue ? State.FAR : State.NEAR;
}

public synchronized void register() {
// It is okay to register multiple times.
mSensorManager.registerListener(this, mProximitySensor, SensorManager.SENSOR_DELAY_UI);
}

public synchronized void unregister() {
mSensorManager.unregisterListener(this);
// Always go back to the FAR state. That way, when we register again we will get a
// transition when the sensor gets into the NEAR state.
mLastState = State.FAR;
}

}



照相主要就是执行了
mCameraAppUi.getPhotoShutter().performClick();这个方法

2》解锁功能实现

找到KeyguardSimpleHostView

解锁用到的方法其实是KeyguardViewBase里面的dismiss()方法

3》相册翻页功能实现

找到photoView,翻页调用的是 slideToNextPicture()方法

4》音乐播放下一曲

找到MediaPlaybackActivity

直接在onSensorChange相应的位置调用

 mPerformanceTestString = NEXT_TEST;
Message msg = mHandler.obtainMessage(NEXT_BUTTON, null);
mHandler.removeMessages(NEXT_BUTTON);
mHandler.sendMessage(msg);

即可

5》收音机换台

找到FmMainActivity

换台调用的是seekStation(mCurrentStation, true);

以上几个应用我都只说具体功能操作的主要方法,没有向照相那样说的详细,

其实大同小异,只是代码加的地方有些不同罢了。

至此,基本已经说完了。

主要还有GestureInductionSettings这个类,它的功能实现可以参考Settings里面的一些

SubSettings来实现。

后续有时间再来补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息