从微信使用摇一摇功能开始,大家就一直喜欢这个简单又刺激的功能,无数个单身男女只要摇摇手中的机子,说不定就能找到终身或一晚的伴侣,这是多奇妙的事呀。
不过摇一摇可不止可以用来搜索同时摇晃手机的人,你还能摇一摇转帐打电话发短信,只要想要。
那摇一摇这个功能是怎么实现的呢?
下面就来看看我用摇一摇实现给默认联系人发送短信,其实只要判断手机晃动速度达到一定的程度就会触发相应的事件,然后作操作就可以拉。
import java.util.ArrayList;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* 这这个是检测摇一摇的类
* @author asdzheng
*/
public class ShakeSensorManager implements SensorEventListener {
private static final int DEFAULT_THRESHOLD_ACCELERATION = 15;
private static final int INTERVAL = 400;
private static SensorManager mSensorManager;
private static ShakeSensorManager mSensorEventListener;
private OnShakeListener mShakeListener;
private Object mLock;
private float mThresholdAcceleration;
private ArrayList<SensorBundle> mSensorBundles;
//回调接口
public static interface OnShakeListener {
/**
* 当检测到摇一摇时调用此方法
*/
public void OnShake();
}
//初始化类
public static boolean create(Context context, OnShakeListener listener) {
if (context == null) {
throw new IllegalArgumentException("Context must not be null");
}
if (mSensorManager == null) {
mSensorManager = (SensorManager) context.getSystemService(
Context.SENSOR_SERVICE);
}
mSensorEventListener = new ShakeSensorManager(listener);
return true;
}
//初始化
private ShakeSensorManager(OnShakeListener listener) {
if (listener == null) {
throw new IllegalArgumentException("Shake listener must not be null");
}
mSensorBundles = new ArrayList<SensorBundle>();
mShakeListener = listener;
mLock = new Object();
mThresholdAcceleration = DEFAULT_THRESHOLD_ACCELERATION;
}
//注册监听器,registerListener最后一个参数是触发后,多久回调函数,我这里选择的是快速
public static boolean start() {
if (mSensorManager != null && mSensorEventListener != null) {
return .registerListener(mSensorEventListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
}
return false;
}
//撤销监听器
public static void stop() {
if (mSensorManager != null) {
mSensorManager.unregisterListener(mSensorEventListener);
}
}
/**
* 释放所有之前用到的类
*/
public static void destroy() {
mSensorManager = null;
mSensorEventListener = null;
}
//更新检测摇晃手机的敏感度,越大越不敏感
public static void updateConfiguration(int sensibility) {
mThresholdAcceleration = sensibility;
}
//这个类是传感器检测到摇晃手机时调用的方法,并把数据sensorEvent里
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
SensorBundle sensorBundle = new SensorBundle(sensorEvent.values[0],
sensorEvent.values[1],
sensorEvent.values[2],
sensorEvent.timestamp);
synchronized (mLock) {
if (mSensorBundles.size() == 0) {
mSensorBundles.add(sensorBundle);
} else if (
sensorBundle.getTimestamp()
- mSensorBundles.get(mSensorBundles.size() - 1).getTimestamp() > INTERVAL) {
//这个判断是防止摇晃手机时多次调用此方法
performCheck(sensorBundle);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
//这个方法是当换掉感应器时才会触发,基本不会调用
}
//判断是否执行摇晃之后的操作
private void performCheck(SensorBundle sensorBundle) {
synchronized (mLock) {
if (Math.abs(sensorBundle.getXAcc()) > mThresholdAcceleration
|| Math.abs(sensorBundle.getYAcc()) > mThresholdAcceleration
|| Math.abs(sensorBundle.getZAcc()) > mThresholdAcceleration) {
mShakeListener.OnShake();
}
}
}
//这个是手机传感器的回调回来的数据
private class SensorBundle {
// x轴方向的重力加速度,向右为正
// y轴方向的重力加速度,向前为正
// z轴方向的重力加速度,向上为正
/**
* The acceleration on X axis.
*/
private final float mXAcc;
/**
* The acceleration on Y axis.
*/
private final float mYAcc;
/**
* The acceleration on Z axis.
*/
private final float mZAcc;
/**
* The timestamp when to record was captured.
*/
private final long mTimestamp;
public SensorBundle(float XAcc, float YAcc, float ZAcc, long timestamp) {
mXAcc = XAcc;
mYAcc = YAcc;
mZAcc = ZAcc;
mTimestamp = timestamp;
}
public float getXAcc() {
return mXAcc;
}
public float getYAcc() {
return mYAcc;
}
public float getZAcc() {
return mZAcc;
}
public long getTimestamp() {
return mTimestamp;
}
}
}
下面这个类是主页面,也是唯一页面,先来看它的截图。
下面再来看主页面的代码:
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.db.ShakeSqliteHelper;
/**
* asdzheng 这是界面
*/
public class MainActivity extends Activity {
private String telnum = "";
private SQLiteDatabase dbWriter;// 获得数据库可写操作的对象
private SQLiteDatabase dbReader;
private ShakeSqliteHelper mySqlite;// 声明继承自SQLiteOpenHelper类的MySqklite
private ImageView iv_head;
private TextView tv_name;
private TextView tv_num;
private Button btn_pick;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySqlite = new ShakeSqliteHelper(this);// 实例化MySqklite对象
dbWriter = mySqlite.getWritableDatabase();// 获得数据库可写操作权限
dbReader = mySqlite.getReadableDatabase();
initView();
//检测到摇一摇是在服务里,这样即使退出这个界面,依旧可以检测到摇一摇
startService(new Intent(this, ShakeService.class));
}
private void initView() {
iv_head = (ImageView) findViewById(R.id.iv_head);
tv_name = (TextView) findViewById(R.id.tv_name);
tv_num = (TextView) findViewById(R.id.tv_telnum);
btn_pick = (Button) findViewById(R.id.btn_pick);
btn_pick.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, 1);
}
});
getUserInfoFromDB();
}
//先从数据库里面取出看是否有以及设置默认联系人
private void getUserInfoFromDB() {
String name = "";
String imagePath = "";
// 游标存储数据
Cursor cursor = dbReader.query(ShakeSqliteHelper.USER_TABLE, null,
null, null, null, null, null);
while (cursor.moveToNext()) {// 判断游标的移动
telnum = cursor.getString(cursor
.getColumnIndex(ShakeSqliteHelper.COLUMN_NUM));
name = cursor.getString(cursor
.getColumnIndex(ShakeSqliteHelper.COLUMN_NAME));
imagePath = cursor.getString(cursor
.getColumnIndex(ShakeSqliteHelper.COLUMN_PATH));
}
setUserInfo(name, imagePath);
}
//如果有的话就设置进界面
private void setUserInfo(String name, String imagePath) {
tv_name.setText(name);
tv_num.setText(telnum);
if (imagePath == null || imagePath.isEmpty()) {
iv_head.setImageResource(R.drawable.ic_launcher);
} else {
iv_head.setImageURI(Uri.parse(imagePath));
}
}
//这是选择联系人后取得返回来的姓名和电话头像图片路径信息
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor cursor = getContentResolver().query(contactData, null, null,
null, null);
if (cursor.moveToFirst()) {
String id = cursor.getString(
cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID)
);
String hasPhone = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)
);
if (hasPhone.equalsIgnoreCase("1")) {
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID+ " = " + id,
null, null);
phones.moveToFirst();
telnum = phones.getString(phones.getColumnIndex("data1"));
}
String name = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
);
String imagePath = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)
);
setUserInfo(name, imagePath);
addUserToDB(name, imagePath);
}
}
}
//成功获取联系人数据后将数据插入数据库
private void addUserToDB(String name, String imagePath) {
String[] args = { "1", name, telnum, imagePath == null ? "" : imagePath };
dbWriter.execSQL("INSERT OR REPLACE INTO "
+ ShakeSqliteHelper.USER_TABLE + " ("
+ ShakeSqliteHelper.COLUNN_ID + ","
+ ShakeSqliteHelper.COLUMN_NAME + ", "
+ ShakeSqliteHelper.COLUMN_NUM + ","
+ ShakeSqliteHelper.COLUMN_PATH + ") VALUES (?, ?, ?, ?)", args);
}
}
现在就到了检测摇一摇事件,并给默认联系人发短信的服务啦
import android.app.Service;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.IBinder;
import android.os.Vibrator;
import android.widget.Toast;
import com.example.db.ShakeSqliteHelper;
import com.example.lib.ShakeSensorManager;
import com.example.lib.ShakeSensorManager.OnShakeListener;
/**
* @author asdzheng
*/
public class ShakeService extends Service implements OnShakeListener {
//这是实现震动的vibrator
private Vibrator vibrator;
//这是设置检测摇一摇的敏感度
private static final int SENSOR_SHAKE = 17;
private SQLiteDatabase dbReader;// 获得数据库可写操作的对象
@Override
public void onCreate() {
//初始化服务
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (ShakeSensorManager.create(this, this)) {
ShakeSensorManager.updateConfiguration(SENSOR_SHAKE);
}
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//注册监听器
ShakeSensorManager.start();
dbReader = new ShakeSqliteHelper(this).getReadableDatabase();
Toast.makeText(ShakeService.this, "Service Start", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
//注销检测器
ShakeSensorManager.stop();
ShakeSensorManager.destroy();
Toast.makeText(ShakeService.this, "Service Destory", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
//检测到摇一摇后的回调函数,震动并发送短信
@Override
public void OnShake() {
vibrator.vibrate(200);
跳到发送界面短信
sendMsg();
}
private void sendMsg() {
String telnum = getTelNum();
if (telnum.isEmpty()) {
return;
}
Uri msgUri = Uri.fromParts("sms", telnum, null);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(msgUri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
//获取电话号码
private String getTelNum() {
String telnum = "";
// 游标存储数据
Cursor cursor = dbReader.query(ShakeSqliteHelper.USER_TABLE, null, null,
null, null, null, null);
while (cursor.moveToNext()) {// 判断游标的移动
telnum = cursor.getString(cursor.getColumnIndex("telnum"));
}
return telnum;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
最后别忘了设置震动和读取联系人信息的权限:
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
这样一个摇一摇发短信的Demo就差不多完成了,我想它这个应用场景是如果你经常给某一人发短信打电话发短信,想简单快速的达到这点,就可以用这个DEMO拉。
时间: 2024-10-14 03:49:31