精华内容
下载资源
问答
  • 短信加密此类功能由于新手学习的需求量较小,所以在网上很少有一些简单的demo供新手参考。笔者做到此处也是花了比较多的时间自我构思,具体的过程也是不过多描述了,讲一下demo的内容。(源码在文章结尾) demo功能...
  • 主要介绍了android实现短信加密功能的相关资料,功能包括发送加密短信、解密本地短信,感兴趣的小伙伴们可以参考一下
  • 短信加密服务

    2014-08-05 10:53:18
    短信 加密服务 实现了 对短信的AES 加密 然后保存加密完的文件到sd卡中
  • 基于安卓手机的短信加密技术,包括实现的原理及代码
  • 安卓手机用户软件下载地址 二选一 1 网页下载地址:http://mmgr.myapp.com/msoft/sec/secure/GodDresser/11/2/3/102021/qqpim_6.7.9.2090_android_20171218170153_main_release_20171219103701_102021.apk 2 ...
    小编心语

          大家好,本公众号为公益账号,无任何收费。所有工作人员作为美丽乡村支教项目的公益使者,始终本着“用大爱做小事”,关心山区孩子教育,帮助弱势群体,希望您也能伸出援手,慷慨解囊,让我们在感恩中共同播撒爱心,相信薪火能相传,梦想将起航,爱心终永驻。有爱就有力量,祝愿山区孩子们能够健康成长,用知识改变命运!如您想伸出援手,请点击下方链接,相信好人有好报

    ☞☞【点击直达】为山区孩子献爱心☜☜

    ★【安卓用户】通讯录同步助手使用教程★



    使用软件说明

    软件名称:QQ同步助手

    应用信息

    【QQ同步助手,备份你的手机生活!】

    换手机必备神器!手机资料自动备份,安全保护防丢失!

    一键备份手机通讯录、软件、照片到云端的超实用工具!

    ------手机随便换,资料不再丢失------

    【智能管理通讯录】

    备份管理:手机通讯录一键备份至网络,随时同步回手机

    快速整理:批量删除联系人,智能合并重复的联系人,省心更省力

    智能检测:自动检测出已失效号码和常用号码,打电话更方便

    随时找回:通过回收站或时光机,随时找回找回误删的联系人

    【照片&软件备份】

    智能备份:根据时间地点智能成相册,一键备份,留住精彩瞬间

    软件恢复:备份常用软件,月光宝盒快速找回,换机不怕麻烦

    【影音秒传】

    免流量面对面传送视频、音乐、照片等,传送方便快捷

    【保护资料安全】

    自动备份:新增/修改联系人自动备份,联系人不再丢失

    帐号保护:新手机用QQ号或微信账号同步资料,可以及时短信预警

    【亲友生日提醒】

    智能匹配通讯录中联系人生日,可一键设置提醒

    【手机百科】

    新增手机百科,实用技巧、新资讯轻松搞定

    安卓手机用户软件下载地址

    二选一

    1 网页下载地址:http://mmgr.myapp.com/msoft/sec/secure/GodDresser/11/2/3/102021/qqpim_6.7.9.2090_android_20171218170153_main_release_20171219103701_102021.apk 2

    软件使用说明视频教学

    ------------------------------------------------------------------------通讯录同步助理可将手机中的名片和短信备份到网络,或从网络恢复到手机,网络存储完备稳定。通讯录同步助理智能同步功能,仅同步手机或网络中发生变化的名片,节省您的流量和时间,采用专业的数字证书加密,对网站、手机客户端进行安全认证,保证您的个人私隐信息安全。通讯录同步助理可将手机中的名片和短信备份到网络,或从网络恢复到手机,网络存储完备稳定。通讯录同步助理智能同步功能,仅同步手机或网络中发生变化的名片,节省您的流量和时间,采用专业的数字证书加密,对网站、手机客户端进行安全认证,保证您的个人私隐信息安全。通讯录同步助理可将手机中的名片和短信备份到网络,或从网络恢复到手机,网络存储完备稳定。通讯录同步助理智能同步功能,仅同步手机或网络中发生变化的名片,节省您的流量和时间,采用专业的数字证书加密,对网站、手机客户端进行安全认证,保证您的个人私隐信息安全。通讯录同步助理可将手机中的名片和短信备份到网络,或从网络恢复到手机,网络存储完备稳定。通讯录同步助理智能同步功能,仅同步手机或网络中发生变化的名片,节省您的流量和时间,采用专业的数字证书加密,对网站、手机客户端进行安全认证,保证您的个人私隐信息安全。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    展开全文
  • 4.车主可以通过Apple的iMessage短信应用程序与其他五个人共享密钥;5.车辆通过iMessage开启后,车主可控制最高速度,马力,收音机最大音量等;6.Apple CarPlay将获得更新,更新后可自定义停车...

    f12e354a206251b53f349ea14972aa4d.png

    1.苹果宣布今后iPhone和Apple Watch可以作为开启和启动车辆的数字钥匙;

    2.支持该系统的第一款汽车将会是宝马5系;

    3.“车钥匙”功能将于下月推送,iOS13上也可使用;

    4.车主可以通过Apple的iMessage短信应用程序与其他五个人共享密钥;

    5.车辆通过iMessage开启后,车主可控制最高速度,马力,收音机最大音量等;

    6.Apple CarPlay将获得更新,更新后可自定义停车、电动汽车充电和点餐三种界面;

    241029d50afc8fd484beb4e9d746e4a6.png

    发短信控制车辆!苹果发布ios14,手机可作车钥匙

    拿出手机,轻按车辆就可解锁;

    进入车辆,将手机放进托盘,就可启动车辆。

    是不是很方便,这本身就是你上车的一系列动作,却在不经意间解锁、启动了车辆。

    6e6da631e0549428dcf4af274f67f867.png

    在今天凌晨的WWDC 2020苹果全球开发者大会上,苹果宣布:将通过数字解决方案,使得手机就可作为解锁、启动的钥匙,该功能将支持即iOS 13和即将推出的iOS 14,今后苹果用户将完全脱离车钥匙。

    宝马将会是第一个用上“手机钥匙”的汽车品牌,苹果正在制定一项标准,使得明年能够有更多汽车品牌用上该功能。

    4935224d949c34a4fb2938f4f83ae961.png

    用手机充当车钥匙,对于安卓用户来说并不是什么新鲜功能,但是苹果对该功能进行进一步优化。

    车主可以通过Apple的iMessage短信应用程序,与其他五个人共享密钥,也就是一部车主手机,可以允许其他5人的苹果手机,也作为车钥匙控制车辆。

    而且车主还可通过短信应用程序,控制其他5人在使用车辆时的最高速度,最大马力,收音机最大音量等其他功能,这项应用更多的是考虑到孩子在使用车辆时,家长对车辆的一种可行性控制。

    7b79b0c0a87b8486cf0c0fc9f0483a78.png

    手机开启车辆通过NFC技术,数字密钥将存在于iPhone的电子钱包应用中。驾驶员只需轻按车辆即可将其解锁,进入车辆后,将手机放入无线充电托盘中并启动车辆。

    你不用担心手机没电,而无法打开车辆。苹果表示,该功能将具有电源保护,在电量不足而关闭后的五个小时内,手机仍可充当钥匙,开启车辆。

    f7b9cc0addf37ea7e649f594181517d6.png

    苹果公司保证了数字钥匙的安全性,称可以从手机上禁用其他驾驶员的钥匙,如果手机丢失,可以通过苹果的云服务iCloud取消数字钥匙对车辆的访问。

    未来,苹果公司将根据iPhone和Apple Watch中的安全硬件创建标准。该硬件标准可确保手机或手表与汽车链接的加密密钥保留在实际设备上,不被其他设备盗取。没有人,甚至是苹果自己,都无法访问这些数据。

    苹果公司已经宣布与汽车行业组织合作,使得数字钥匙系统可与更多汽车一起使用。并希望在明年,将该功能会扩展到其他车辆。

    67a2a1b4f5d80598d2263e8ff4247e9d.png

    在凌晨的WWDC 2020苹果全球开发者大会上,苹果还宣布Apple CarPlay将获得更新。

    用户可以选择自定义背景作为墙纸,此外,新的界面中允许使用三种不同的场景,包括停车等待、纯电汽车充电和点餐等待。

    未来,苹果将更加注重纯电汽车系统开发,Apple Map将添加电动车路线,标记沿途的充电站,并结合路程和车辆剩余电量,选取最优路线。

    本文来源于汽车之家车家号作者,不代表汽车之家的观点立场。

    展开全文
  • 注意:本项目基于android studio开发,eclipse可能无法直接导入。
  • 这是 Secure SMS Andriod 应用程序的自述文件。 这将使您能够加密和发送短信。 用户然后可以通过选择的密钥解锁并查看消息。 请参阅以下链接以获取原型。
  • 基于3DES和RSA的Android系统短信加密设计与实现.pdf
  • Android 4.4短信源码修改扩充过程中,为了实现短信会话加密,使用了sh

    转载请注明出处:周木水的CSDN博客 http://blog.csdn.net/zhoumushui


    1.九宫格手势密码与字符密保实现短信加密,解密

    在上个项目Android 4.4短信源码修改扩充过程中,为了实现短信会话加密,使用了手势密码,通过SharedPreferences的存储方式实现,今天就简单回顾一下。

    先上个效果图:



    由于代码集成于源码com.android.mms包中,依赖较多,需要在源码环境下编译,今天我就贴出来核心代码,等闲时再整理出可独立安装的Demo。

    由于整个项目就是仿造微信电话本,分析了com.tencent.pb的一些逻辑之后,我发现微信电话本的加密逻辑应该是:将短信会话(具有相同threadId的所有短信存储到自定义数据库,然后从系统数据库中删掉。解密刚好相反。

    既然逻辑已经清晰,剩下的就简单了,开工:

    在一个短信会话中点击“加密会话”后,用一个case响应,获取到这个会话的threadId,然后调用加密函数:

    case MENU_ADD_LOCK:
    			int zjThreadId = (int) (mConversation.getThreadId());
    			zjSaveMsg(zjThreadId);
    			break;

    核心的来了,加密过程:

    // zj add part for Lock Msg start
    	public void zjSaveMsg(int threadId) {
    		String strId = Integer.toString(threadId);
    		// int count=0;
    		Uri uri = Uri.parse("content://sms");
    		// Uri uri, String[] projection, String selection,String[]
    		// selectionArgs, String sortOrder
    		String selection = "thread_id=?";
    		String[] selectionArgs = new String[] { strId };
    		Cursor cur = this.managedQuery(uri, null, selection, selectionArgs,
    				null);
    		if (cur.moveToFirst()) {
    			do {
    				// for(int j = 0; j < cur.getColumnCount(); j++){
    				// String info = "name:" + cur.getColumnName(j) + "=" +
    				// cur.getString(j);
    				// Log.i("====>", info);
    				// }
    				// to zj DB start
    				MmsLockMsgDbHelper _db = new MmsLockMsgDbHelper(this);
    				int newMsgId = -1;
    				// long address = Long.parseLong(cur.getString(2));
    				// long date = Long.parseLong(cur.getString(4));
    				// int type = Integer.parseInt(cur.getString(9));
    				// String body = cur.getString(12);
    				int addressIndex = cur.getColumnIndex("address");
    				int dateIndex = cur.getColumnIndex("date");
    				int typeIndex = cur.getColumnIndex("type");
    				int bodyIndex = cur.getColumnIndex("body");
    				long address = Long.parseLong(cur.getString(addressIndex));
    				long date = Long.parseLong(cur.getString(dateIndex));
    				int type = Integer.parseInt(cur.getString(typeIndex));
    				String body = cur.getString(bodyIndex);
    				String phoneNum = Long.toString(address);
    				String name = getNameByNumber(phoneNum);
    				if (name != null && name.trim().length() > 0) {
    					MmsLockMsg newMsg = new MmsLockMsg(threadId, address, date,
    							type, body, name);
    					newMsgId = _db.addMsg(newMsg);
    				} else {
    					MmsLockMsg newMsg = new MmsLockMsg(threadId, address, date,
    							type, body, phoneNum);
    					newMsgId = _db.addMsg(newMsg);
    				}
    
    				// to zj DB end
    			} while (cur.moveToNext());
    		}
    		// delete from SystemDb start
    		this.getContentResolver().delete(Uri.parse("content://sms"),
    				"thread_id=?", new String[] { strId });
    		// delete from SystemDb end
    		Toast.makeText(this, com.android.mms.R.string.zj_lock_success,
    				Toast.LENGTH_SHORT).show();
    		finish();
    		// add for animation start
    		if (version > 5) {
    			overridePendingTransition(com.android.mms.R.anim.zj_right_in,
    					com.android.mms.R.anim.zj_right_out);
    		}
    		// add for animation end
    	}

    短信收藏的代码顺便也贴一下吧,也是容易实现的,与加密相比少了一步,没有从系统数据库删掉,并且收藏只是收藏单条短信,而不是整个会话,所以接口要在短信条目长按的菜单里面添加:

    case MENU_ADD_MARK:
    				int sms_id = (int) (mMsgItem.mMsgId);
    				Log.e("SMS_ID", "" + sms_id);
    				// Toast.makeText(this, ""+sms_id, 2).show();
    				zjSaveMark(sms_id);
    				return true;

    public void zjSaveMark(int sms_id) {
    		MmsMarkMsgDbHelper _db2 = new MmsMarkMsgDbHelper(this);
    		// _db.onUpgrade(db, oldVersion, newVersion);
    		String strId = Integer.toString(sms_id);
    		int smsCount = 0;
    		try {
    			Cursor countCur = _db2.getAllMsgBySmsId(sms_id);
    			smsCount = countCur.getCount(); // zj:查看是否已经收藏
    		} catch (Exception e) {
    			// _db.onCreate(_db);
    		}
    		Log.e("smsCount", "" + smsCount);
    		if (smsCount > 0) {
    			Toast.makeText(this, com.android.mms.R.string.zj_already_marked,
    					Toast.LENGTH_SHORT).show();
    		} else {
    			// int count=0;
    			Uri uri = Uri.parse("content://sms");
    			// Uri uri, String[] projection, String selection,String[]
    			// selectionArgs, String sortOrder
    			String selection = "_id=?";
    			String[] selectionArgs = new String[] { strId };
    			Cursor cur = this.managedQuery(uri, null, selection, selectionArgs,
    					null);
    			if (cur.moveToFirst()) {
    				do {
    					// to zj DB start
    
    					int newMsgId = -1;
    					int addressIndex = cur.getColumnIndex("address");
    					int dateIndex = cur.getColumnIndex("date");
    					int typeIndex = cur.getColumnIndex("type");
    					int bodyIndex = cur.getColumnIndex("body");
    					long address = Long.parseLong(cur.getString(addressIndex));
    					long date = Long.parseLong(cur.getString(dateIndex));
    					int type = Integer.parseInt(cur.getString(typeIndex));
    					String body = cur.getString(bodyIndex);
    					MmsMarkMsg newMsg = new MmsMarkMsg(sms_id, address, date,
    							type, body);
    					newMsgId = _db2.addMsg(newMsg);
    					// to zj DB end
    				} while (cur.moveToNext());
    			}
    			Toast.makeText(this, com.android.mms.R.string.zj_mark_success,
    					Toast.LENGTH_SHORT).show();
    		}
    
    	}

    查看加密的短信需要进入到一个List,进入之前需要进行身份验证。

    如果是第一次进入,之前没有设置过九宫格手势密码,就提示用户设置,第一次绘制和第二次绘制图案相同,设置手势密码成功,然后提示用户设置字符密保,用于忘记手势密码时进行重置。

    验证身份页面:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import java.util.Random;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.Window;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    import android.app.ActionBar; //zj add for actionBar back
    
    public class MmsLock extends Activity {
    
    	private LinearLayout nine_con;
    	MmsLockSetPwd setPwd;
    	MmsLockCheckPwd checkPwd;
    	TextView showInfo;
    	boolean isSetFirst = false;
    	public int version = Integer.valueOf(android.os.Build.VERSION.SDK);
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    
    		super.onCreate(savedInstanceState);
    
    		// this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    		setContentView(com.android.mms.R.layout.mms_lock);
    		showInfo = (TextView) findViewById(com.android.mms.R.id.show_set_info);
    
    		nine_con = (LinearLayout) findViewById(com.android.mms.R.id.nine_con);
    
    		SharedPreferences shareDate = getSharedPreferences("GUE_PWD", 0);
    		String pwd = shareDate.getString("GUE_PWD", "HAVE NO PWD !");
    		boolean is_set = shareDate.getBoolean("IS_SET", false);
    
    		if (is_set) {
    			TextView tv_forget_pwd = (TextView) findViewById(com.android.mms.R.id.zj_lock_forget_pwd);
    			checkPwd = new MmsLockCheckPwd(MmsLock.this);
    			nine_con.addView(checkPwd);
    			tv_forget_pwd.setVisibility(View.VISIBLE);
    			checkPwd();
    		} else {
    			TextView tv_forget_pwd = (TextView) findViewById(com.android.mms.R.id.zj_lock_forget_pwd);
    			setPwd = new MmsLockSetPwd(MmsLock.this);
    			nine_con.addView(setPwd);
    			tv_forget_pwd.setVisibility(View.GONE);
    			getSetPwd();
    
    		}
    
    		// zj:for action back start
    		ActionBar actionBar = getActionBar();
    		actionBar.setHomeButtonEnabled(true);
    		actionBar.setDisplayHomeAsUpEnabled(true);
    		actionBar.setDisplayShowHomeEnabled(true);
    		// zj:for action bar end
    
    	}
    
    	public void checkPwd() {
    		showInfo.setText(com.android.mms.R.string.zj_check_pwd);
    		SharedPreferences shareDate = getSharedPreferences("GUE_PWD", 0);
    	}
    
    	public void getSetPwd() {
    
    		SharedPreferences shareDate = getSharedPreferences("GUE_PWD", 0);
    		isSetFirst = shareDate.getBoolean("IS_SET_FIRST", false);
    		if (!isSetFirst) {
    			showInfo.setText(com.android.mms.R.string.zj_set_pwd);
    			shareDate.edit().clear().commit();
    		} else {
    			showInfo.setText(com.android.mms.R.string.zj_confirm_pwd);
    		}
    
    		boolean is_second_error = shareDate.getBoolean("SECOND_ERROR", false);
    		if (is_second_error) {
    			showInfo.setText(com.android.mms.R.string.zj_reinput_pwd);
    			shareDate.edit().clear().commit();
    		}
    	}
    
    	// zj actionBar Menu start
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		// Inflate the menu; this adds items to the action bar if it is present.
    		getMenuInflater().inflate(com.android.mms.R.menu.mms_lock, menu);
    		return true;
    	}
    
    	@Override
    	public boolean onOptionsItemSelected(MenuItem item) {
    		switch (item.getItemId()) {
    		case android.R.id.home:
    			finish();
    			// add for animation start
    			if (version > 5) {
    				overridePendingTransition(com.android.mms.R.anim.zj_right_in,
    						com.android.mms.R.anim.zj_right_out);
    			}
    			// add for animation end
    			break;
    //		case com.android.mms.R.id.zj_reset_pwd:
    //			Intent intent = new Intent(this,
    //					com.android.mms.ui.MmsLockResetPwd.class);
    //			startActivity(intent);
    //			break;
    
    		default:
    			// return super.onOptionsItemSelected(item);
    			break;
    		}
    		return true;
    	}
    
    	// zj actionBar menu end
    
    	public void zjForgetPwd(View v) {
    		Intent intent = new Intent(this,
    				com.android.mms.ui.MmsLockResetPwd.class);
    		startActivity(intent);
    	}
    
    }


    加密短信的DbHelper:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    public class MmsLockMsgDbHelper extends SQLiteOpenHelper {
    	private static final int DATABASE_VERSION = 3;
    	private static final String DATABASE_NAME = "zj_msg";
    
    	private static final String NOTE_TABLE_NAME = "msg";
    	private static final String NOTE_COL_ID = "_id";
    	private static final String NOTE_COL_THREAD_ID = "thread_id";
    	private static final String NOTE_COL_ADDRESS = "address";
    	private static final String NOTE_COL_DATE = "date";
    	private static final String NOTE_COL_TYPE = "type";
    	private static final String NOTE_COL_BODY = "body";
    	private static final String NOTE_COL_NAME = "name";
    
    	private static final String[] NOTE_COL_PROJECTION = new String[] {
    			NOTE_COL_ID, NOTE_COL_THREAD_ID, NOTE_COL_ADDRESS, NOTE_COL_DATE,
    			NOTE_COL_TYPE, NOTE_COL_BODY, NOTE_COL_NAME };
    
    	public MmsLockMsgDbHelper(Context context) {
    		super(context, DATABASE_NAME, null, DATABASE_VERSION);
    	}
    
    	// Create table
    	@Override
    	public void onCreate(SQLiteDatabase db) {
    		String createNOTETableSql = "CREATE TABLE " + NOTE_TABLE_NAME + " ("
    				+ NOTE_COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
    				+ NOTE_COL_THREAD_ID + " INTEGER," + NOTE_COL_ADDRESS
    				+ " INTEGER," + NOTE_COL_DATE + " INTEGER," + NOTE_COL_TYPE
    				+ " INTEGER," + NOTE_COL_BODY + " TEXT," + NOTE_COL_NAME
    				+ " TEXT" + ");";
    		db.execSQL(createNOTETableSql);
    	}
    
    	@Override
    	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    		// Drop older table if existed
    		db.execSQL("DROP TABLE IF EXISTS " + NOTE_TABLE_NAME);
    
    		// Create tables again
    		onCreate(db);
    	}
    
    	// Add new Msg
    	public int addMsg(MmsLockMsg Msg) {
    		SQLiteDatabase db = this.getWritableDatabase();
    
    		ContentValues values = new ContentValues();
    		values.put(NOTE_COL_THREAD_ID, Msg.getThreadId());
    		values.put(NOTE_COL_ADDRESS, Msg.getAddress());
    		values.put(NOTE_COL_DATE, Msg.getDate());
    		values.put(NOTE_COL_TYPE, Msg.getType());
    		values.put(NOTE_COL_BODY, Msg.getBody());
    		values.put(NOTE_COL_NAME,Msg.getName());
    
    		// Insert to database
    		long rowId = db.insert(NOTE_TABLE_NAME, null, values);
    
    		// Close the database
    		db.close();
    
    		return (int) rowId;
    	}
    
    	// Get one NOTE
    	public MmsLockMsg getMsg(int id) {
    		SQLiteDatabase db = this.getReadableDatabase();
    
    		Cursor cursor = db.query(NOTE_TABLE_NAME, NOTE_COL_PROJECTION,
    				NOTE_COL_ID + "=?", new String[] { String.valueOf(id) }, null,
    				null, null, null);
    
    		if (cursor != null)
    			cursor.moveToFirst();
    
    		MmsLockMsg msg = new MmsLockMsg(cursor.getInt(0), cursor.getInt(1),
    				cursor.getLong(2), cursor.getLong(3), cursor.getInt(4),
    				cursor.getString(5),cursor.getString(6));
    
    		return msg;
    	}
    
    	public int getThreadIdById(int id) {
    		SQLiteDatabase db = this.getReadableDatabase();
    		Cursor cursor = db.query(NOTE_TABLE_NAME, NOTE_COL_PROJECTION,
    				NOTE_COL_ID + "=?", new String[] { String.valueOf(id) }, null,
    				null, null, null);
    		if (cursor != null)
    			cursor.moveToFirst();
    		int threadId = cursor.getInt(1);
    		return threadId;
    	}
    
    	// Get all Msg
    	public List<MmsLockMsg> getAllMsg() {
    		List<MmsLockMsg> MsgList = new ArrayList<MmsLockMsg>();
    		String selectQuery = "SELECT * FROM " + NOTE_TABLE_NAME;
    
    		SQLiteDatabase db = this.getWritableDatabase();
    		Cursor cursor = db.rawQuery(selectQuery, null);
    
    		// looping through all rows and adding to list
    		if (cursor.moveToFirst()) {
    			do {
    				MmsLockMsg Msg = new MmsLockMsg(cursor.getInt(0),
    						cursor.getInt(1), cursor.getLong(2), cursor.getLong(3),
    						cursor.getInt(4), cursor.getString(5),cursor.getString(6));
    				MsgList.add(Msg);
    			} while (cursor.moveToNext());
    		}
    
    		// return contact list
    		return MsgList;
    	}
    
    	public Cursor getAllMsgCursor() {
    		String selectQuery = "SELECT * FROM " + NOTE_TABLE_NAME;
    
    		SQLiteDatabase db = this.getReadableDatabase();
    		Cursor cursor = db.rawQuery(selectQuery, null);
    		return cursor;
    	}
    
    	public Cursor getAllMsgCursorGroupByThreadId() {
    		String selectQuery = "SELECT * FROM msg WHERE _id in (select min(_id)from msg group by thread_id)";
    
    		SQLiteDatabase db = this.getReadableDatabase();
    		Cursor cursor = db.rawQuery(selectQuery, null);
    		return cursor;
    	}
    
    	// 更改电话号码为联系人名字,若存在
    	// public Cursor
    
    
    
    	public Cursor getAllMsgByThreadId(int threadId) {
    		String selectQuery = "SELECT * FROM msg WHERE thread_id =" + threadId
    				+ " order by date";
    
    		SQLiteDatabase db = this.getReadableDatabase();
    		Cursor cursor = db.rawQuery(selectQuery, null);
    		return cursor;
    	}
    
    	public int updateMsg(MmsLockMsg msg) {
    		SQLiteDatabase db = this.getWritableDatabase();
    
    		ContentValues values = new ContentValues();
    		values.put(NOTE_COL_THREAD_ID, msg.getThreadId());
    		values.put(NOTE_COL_ADDRESS, msg.getAddress());
    		values.put(NOTE_COL_DATE, msg.getDate());
    		values.put(NOTE_COL_TYPE, msg.getType());
    		values.put(NOTE_COL_BODY, msg.getBody());
    		values.put(NOTE_COL_NAME, msg.getName());
    
    		return db.update(NOTE_TABLE_NAME, values, NOTE_COL_ID + "=?",
    				new String[] { String.valueOf(msg.getId()) });
    	}
    
    	public void deleteMsg(int id) {
    		SQLiteDatabase db = this.getWritableDatabase();
    		db.delete(NOTE_TABLE_NAME, NOTE_COL_ID + "=?",
    				new String[] { String.valueOf(id) });
    		db.close();
    	}
    
    	public void deleteMsgByThreadId(int threadId) { // NOTE_COL_ID改为NOTE_COL_THREAD_ID
    		SQLiteDatabase db = this.getWritableDatabase();
    		db.delete(NOTE_TABLE_NAME, NOTE_COL_THREAD_ID + "=?",
    				new String[] { String.valueOf(threadId) });
    		db.close();
    	}
    
    	public void deleteAllMsg() {
    		SQLiteDatabase db = this.getWritableDatabase();
    		db.delete(NOTE_TABLE_NAME, null, null);
    		db.close();
    	}
    
    }
    



    文件有些多,今天就先到这儿吧,明天再续。有不明白的地方欢迎交流。



    洗衣机坏了,有时候按一会儿就可以启动了,今天怎么弄都没效果,大概是启动电容的问题吧,悲剧。

    下午去看公司部门间的球赛,我们队再胜一局,维持不败战绩,作为拉拉队员还是很开心的。

    今天接着昨天的内容开始~

    哎呀,代码在公司,明天再补充。先去学习。


    Mms类:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    public class MmsLockMsg {
    
    	int _id;
    	int thread_id; // 号码区分标识
    	long address; // 号码
    	long date; // 日期
    	int type;//信息类型
    	// long date_sent; // 发送日期
    	String body; // 短信内容
    	String name;
    
    	public MmsLockMsg(int id, int thread_id, long address, long date,int type,String body,String name) {
    		this._id = id;
    		this.thread_id = thread_id;
    		this.address = address;
    		this.date = date;
    		this.type =type;
    		this.body = body;
    		this.name = name;
    	}
    	public MmsLockMsg(int thread_id, long address, long date,int type, String body,String name) {
    		this.thread_id = thread_id;
    		this.address = address;
    		this.date = date;
    		this.type =type;
    		this.body = body;
    		this.name = name;
    	}
    	
    
    	public int getId() {
    		return _id;
    	}
    
    	public int getThreadId() {
    		return thread_id;
    	}
    
    	public void setThreadId(int thread_id) {
    		this.thread_id = thread_id;
    	}
    
    	public long getAddress() {
    		return address;
    	}
    
    	public void setAddress(long address) {
    		this.address = address;
    	}
    
    	public long getDate() {
    		return date;
    	}
    
    	public void setDate(long date) {
    		this.date = date;
    	}
    	public int getType(){
    		return type;
    	}
    	public void setType(int type){
    		this.type=type;
    	}
    
    	public String getBody() {
    		return body;
    	}
    
    	public void setBody(String body) {
    		this.body = body;
    	}
    	public String getName(){
    		return name;
    	}
    	public void setName(String name){
    		this.name = name;
    	}
    
    }
    


    设置手势密码页:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.graphics.Typeface;
    import android.graphics.Paint.Cap;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    public class MmsLockSetPwd extends View {
    	TextView tv_forget_pwd = (TextView)findViewById(com.android.mms.R.id.zj_lock_forget_pwd);
    	Paint linePaint = new Paint();
    	Paint whiteLinePaint = new Paint();
    	Paint textPaint = new Paint();
    	Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.lock);
    	int defaultBitmapRadius = defaultBitmap.getWidth() / 2;
    	Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.indicator_lock_area);
    	int selectedBitmapDiameter = selectedBitmap.getWidth();
    	int selectedBitmapRadius = selectedBitmapDiameter / 2;
    	PointInfo[] points = new PointInfo[9];
    	PointInfo startPoint = null;
    	int width, height;
    	int moveX, moveY;
    	boolean isUp = false;
    	Context ctx;
    	StringBuffer lockString = new StringBuffer();
    
    	public MmsLockSetPwd(Context context) {
    		
    
    		super(context);
    		ctx = context;
    		// this.setBackgroundColor(Color.WHITE);
    		initPaint();
    	}
    
    	public MmsLockSetPwd(Context context, AttributeSet attrs) {
    
    		super(context, attrs);
    
    		// this.setBackgroundColor(Color.WHITE);
    		tv_forget_pwd.setVisibility(View.GONE); //zj add 
    
    
    		initPaint();
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
    		width = getWidth();
    		height = getHeight();
    		if (width != 0 && height != 0) {
    			initPoints(points);
    		}
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int left, int top, int right,
    			int bottom) {
    		super.onLayout(changed, left, top, right, bottom);
    	}
    	private int startX = 0, startY = 0;
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		// canvas.drawText("passwd:" + lockString, 0, 40, textPaint);
    
    		if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
    			// drawLine(canvas, startX, startY, moveX, moveY);
    		}
    		drawNinePoint(canvas);
    		super.onDraw(canvas);
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    
    		boolean flag = true;
    
    		if (isUp) {
    			finishDraw();
    			flag = false;
    		} else {
    			handlingEvent(event);
    			flag = true;
    		}
    		return flag;
    	}
    
    	private void handlingEvent(MotionEvent event) {
    
    		switch (event.getAction()) {
    
    		case MotionEvent.ACTION_MOVE:
    			moveX = (int) event.getX();
    			moveY = (int) event.getY();
    			for (PointInfo temp : points) {
    				if (temp.isInMyPlace(moveX, moveY)
    						&& temp.isSelected() == false) {
    					temp.setSelected(true);
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					int len = lockString.length();
    					if (len != 0) {
    						int preId = lockString.charAt(len - 1) - 48;
    						points[preId].setNextId(temp.getId());
    					}
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    
    			invalidate(0, height - width, width, height);
    
    			break;
    
    		case MotionEvent.ACTION_DOWN:
    
    			int downX = (int) event.getX();
    			int downY = (int) event.getY();
    			for (PointInfo temp : points) {
    
    				if (temp.isInMyPlace(downX, downY)) {
    
    					temp.setSelected(true);
    					startPoint = temp;
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    
    			invalidate(0, height - width, width, height);
    
    			break;
    
    		case MotionEvent.ACTION_UP:
    
    			startX = startY = moveX = moveY = 0;
    			isUp = true;
    			invalidate();
    			savePwd();
    			break;
    		default:
    			break;
    		}
    	}
    
    	private void finishDraw() {
    
    		for (PointInfo temp : points) {
    			temp.setSelected(false);
    			temp.setNextId(temp.getId());
    		}
    
    		lockString.delete(0, lockString.length());
    		isUp = false;
    		invalidate();
    	}
    
    	private void initPoints(PointInfo[] points) {
    
    		int len = points.length;
    		int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;
    		int seletedX = seletedSpacing;
    		int seletedY = height - width + seletedSpacing;
    		int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
    		int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;
    
    		for (int i = 0; i < len; i++) {
    
    			if (i == 3 || i == 6) {
    
    				seletedX = seletedSpacing;
    				seletedY += selectedBitmapDiameter + seletedSpacing;
    				defaultX = seletedX + selectedBitmapRadius
    						- defaultBitmapRadius;
    				defaultY += selectedBitmapDiameter + seletedSpacing;
    
    			}
    
    			points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);
    			seletedX += selectedBitmapDiameter + seletedSpacing;
    			defaultX += selectedBitmapDiameter + seletedSpacing;
    
    		}
    	}
    
    	private void initPaint() {
    
    		initLinePaint(linePaint);
    		initTextPaint(textPaint);
    		initWhiteLinePaint(whiteLinePaint);
    
    	}
    
    	/**
    	 * @param paint
    	 */
    	private void initTextPaint(Paint paint) {
    
    		textPaint.setTextSize(30);
    		textPaint.setAntiAlias(true);
    		textPaint.setTypeface(Typeface.MONOSPACE);
    
    	}
    
    	/**
    	 * @param paint
    	 */
    	private void initLinePaint(Paint paint) {
    
    		//paint.setColor(Color.GRAY);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		//paint.setStyle(Style.STROKE);
    		paint.setStyle(Style.FILL);
    		
    		paint.setStrokeWidth(10);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    
    	}
    
    	/**
    	 * @param paint
    	 */
    	private void initWhiteLinePaint(Paint paint) {
    		//paint.setColor(Color.WHITE);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		paint.setStrokeWidth(8);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 */
    	private void drawNinePoint(Canvas canvas) {
    
    		if (startPoint != null) {
    			drawEachLine(canvas, startPoint);
    
    		}
    
    		for (PointInfo pointInfo : points) {
    			if (pointInfo != null) {
    				if (pointInfo.isSelected()) {
    					canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
    							pointInfo.getSeletedY(), null);
    				}else{	// zj add
    				canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
    						pointInfo.getDefaultY(), null);
    				}
    			}
    		}
    
    	}
    
    	/**
    	 * @param canvas
    	 * @param point
    	 */
    	private void drawEachLine(Canvas canvas, PointInfo point) {
    		if (point.hasNextId()) {
    			int n = point.getNextId();
    			drawLine(canvas, point.getCenterX(), point.getCenterY(),
    					points[n].getCenterX(), points[n].getCenterY());
    			drawEachLine(canvas, points[n]);
    		}
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 * @param startX
    	 * @param startY
    	 * @param stopX
    	 * @param stopY
    	 */
    	private void drawLine(Canvas canvas, float startX, float startY,
    			float stopX, float stopY) {
    		canvas.drawLine(startX, startY, stopX, stopY, linePaint);
    		canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
    	}
    
    	/**
    	 * @author zkwlx
    	 * 
    	 */
    	private class PointInfo {
    
    		private int id;
    		private int nextId;
    		private boolean selected;
    		private int defaultX;
    		private int defaultY;
    		private int seletedX;
    		private int seletedY;
    
    		public PointInfo(int id, int defaultX, int defaultY, int seletedX,
    				int seletedY) {
    			this.id = id;
    			this.nextId = id;
    			this.defaultX = defaultX;
    			this.defaultY = defaultY;
    			this.seletedX = seletedX;
    			this.seletedY = seletedY;
    		}
    
    		public boolean isSelected() {
    			return selected;
    		}
    
    		public void setSelected(boolean selected) {
    			this.selected = selected;
    		}
    
    		public int getId() {
    			return id;
    		}
    
    		public int getDefaultX() {
    			return defaultX;
    		}
    
    		public int getDefaultY() {
    			return defaultY;
    		}
    
    		public int getSeletedX() {
    			return seletedX;
    		}
    
    		public int getSeletedY() {
    			return seletedY;
    		}
    
    		public int getCenterX() {
    			return seletedX + selectedBitmapRadius;
    		}
    
    		public int getCenterY() {
    			return seletedY + selectedBitmapRadius;
    		}
    
    		public boolean hasNextId() {
    			return nextId != id;
    		}
    
    		public int getNextId() {
    			return nextId;
    		}
    
    		public void setNextId(int nextId) {
    			this.nextId = nextId;
    		}
    
    		/**
    		 * @param x
    		 * @param y
    		 */
    		public boolean isInMyPlace(int x, int y) {
    			boolean inX = x > seletedX
    					&& x < (seletedX + selectedBitmapDiameter);
    			boolean inY = y > seletedY
    					&& y < (seletedY + selectedBitmapDiameter);
    			return (inX && inY);
    		}
    
    	}
    
    	public String getPwd() {
    		return lockString.toString();
    
    	}
    
    	public void savePwd() {
    		Intent intent = new Intent();
    		SharedPreferences shareDate = ctx.getSharedPreferences("GUE_PWD", 0);
    		boolean isSetFirst = shareDate.getBoolean("IS_SET_FIRST", false);
    		if (isSetFirst) {
    			String pwd = this.getPwd();
    			String first_pwd = shareDate.getString("FIRST_PWD", "HAVE NO PWD");
    			if (pwd.equals(first_pwd)) {
    				shareDate.edit().clear().commit();
    				shareDate.edit().putBoolean("IS_SET", true).commit();
    				shareDate.edit().putString("GUE_PWD", pwd).commit();
    				intent.setClass(ctx, MmsLockSetPwdOk.class);
    			} else {
    				shareDate.edit().putBoolean("SECOND_ERROR", true).commit();
    				intent.setClass(ctx, MmsLock.class);
    			}
    		} else {
    			shareDate.edit().clear().commit();
    			shareDate.edit().putString("FIRST_PWD", this.getPwd()).commit();
    			shareDate.edit().putBoolean("IS_SET_FIRST", true).commit();
    			intent.setClass(ctx, MmsLock.class);
    		}
    
    		ctx.startActivity(intent);
    
    		((Activity) ctx).finish();
    
    	}
    
    
    }
    

    手势密码设置成功后,让用户输入字符密保,以防遗忘手势密码:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import android.app.Activity;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.os.Bundle;
    import android.view.View;
    import android.view.Window;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MmsLockSetPwdOk extends Activity {
    	
    	//private TextView showInfo;
    	private EditText secondPwd;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		super.onCreate(savedInstanceState);		
    		//this.requestWindowFeature(Window.FEATURE_NO_TITLE);		
    		setContentView(com.android.mms.R.layout.mms_lock_res);		
    		//showInfo = (TextView)findViewById(com.android.mms.R.id.res_info);	
    
    		//SharedPreferences shareDate = getSharedPreferences("GUE_PWD", 0);	
    		//String pwd = shareDate.getString("GUE_PWD", "HAVE NO PWD !");
    		
    //		showInfo.setText("密码是: "+pwd);
    		//showInfo.setText(com.android.mms.R.string.zj_set_pwd_tip);
    	}
    	
    	public void saveSecondPwd(View v){
    		secondPwd = (EditText)findViewById(com.android.mms.R.id.second_pwd);
    		String secondStr = secondPwd.getText().toString();
    		if(secondStr!= null && secondStr.trim().length() != 0){
            //获取SharedPreferences对象
           // Context ctx = MainActivity.this;       
            SharedPreferences secondShare = getSharedPreferences("SECOND_PWD", MODE_PRIVATE);
            //存入数据
            Editor editor = secondShare.edit();
            editor.putString("SECOND_KEY", secondStr);
            editor.putBoolean("SECOND_IS_SET", true);
            editor.commit();
            Toast.makeText(this, com.android.mms.R.string.zj_set_pwd_success, Toast.LENGTH_SHORT).show();
            finish();
    		}else{
    			Toast.makeText(this, com.android.mms.R.string.zj_pwd_null, Toast.LENGTH_SHORT).show();
    		}
    	}
    }
    



    MmsLockCheckPwd.java:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.graphics.Paint.Cap;
    import android.graphics.Paint.Style;
    //import android.os.Vibrator; // zj Cancel 
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    public class MmsLockCheckPwd extends View {
    	TextView tv_forget_pwd = (TextView) findViewById(com.android.mms.R.id.zj_lock_forget_pwd);
    
    	Paint linePaint = new Paint();
    	Paint whiteLinePaint = new Paint();
    	Paint textPaint = new Paint();
    	Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.lock);
    	int defaultBitmapRadius = defaultBitmap.getWidth() / 2;
    	Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.indicator_lock_area);
    	int selectedBitmapDiameter = selectedBitmap.getWidth();
    	int selectedBitmapRadius = selectedBitmapDiameter / 2;
    	PointInfo[] points = new PointInfo[9];
    	PointInfo startPoint = null;
    	int width, height;
    	int moveX, moveY;
    	boolean isUp = false;
    	Context ctx;
    	StringBuffer lockString = new StringBuffer();
    
    	public MmsLockCheckPwd(Context context) {
    
    		super(context);
    		ctx = context;
    		// this.setBackgroundColor(Color.WHITE);
    		initPaint();
    	}
    
    	public MmsLockCheckPwd(Context context, AttributeSet attrs) {
    		super(context, attrs);
    
    		// this.setBackgroundColor(Color.WHITE);
    		tv_forget_pwd.setVisibility(View.VISIBLE); // zj add
    		initPaint();
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		width = getWidth();
    		height = getHeight();
    		if (width != 0 && height != 0) {
    			initPoints(points);
    		}
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int left, int top, int right,
    			int bottom) {
    		super.onLayout(changed, left, top, right, bottom);
    	}
    
    	private int startX = 0, startY = 0;
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    
    		// canvas.drawText("passwd:" + lockString, 0, 40, textPaint);
    		if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
    			// drawLine(canvas, startX, startY, moveX, moveY);
    		}
    		drawNinePoint(canvas);
    		super.onDraw(canvas);
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    
    		boolean flag = true;
    		if (isUp) {
    			finishDraw();
    			flag = false;
    		} else {
    			handlingEvent(event);
    			flag = true;
    		}
    		return flag;
    	}
    
    	private void handlingEvent(MotionEvent event) {
    
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_MOVE:
    			moveX = (int) event.getX();
    			moveY = (int) event.getY();
    			for (PointInfo temp : points) {
    				if (temp.isInMyPlace(moveX, moveY)
    						&& temp.isSelected() == false) {
    					temp.setSelected(true);
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					int len = lockString.length();
    					if (len != 0) {
    						int preId = lockString.charAt(len - 1) - 48;
    						points[preId].setNextId(temp.getId());
    					}
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    			invalidate(0, height - width, width, height);
    			break;
    
    		case MotionEvent.ACTION_DOWN:
    
    			int downX = (int) event.getX();
    			int downY = (int) event.getY();
    			for (PointInfo temp : points) {
    				if (temp.isInMyPlace(downX, downY)) {
    					temp.setSelected(true);
    					startPoint = temp;
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    			invalidate(0, height - width, width, height);
    			break;
    
    		case MotionEvent.ACTION_UP:
    			startX = startY = moveX = moveY = 0;
    			isUp = true;
    			invalidate();
    			savePwd();
    			break;
    		default:
    			break;
    		}
    	}
    
    	private void finishDraw() {
    		for (PointInfo temp : points) {
    			temp.setSelected(false);
    			temp.setNextId(temp.getId());
    		}
    		lockString.delete(0, lockString.length());
    		isUp = false;
    		invalidate();
    	}
    
    	private void initPoints(PointInfo[] points) {
    
    		int len = points.length;
    		int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;
    		int seletedX = seletedSpacing;
    		int seletedY = height - width + seletedSpacing;
    		int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
    		int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;
    
    		for (int i = 0; i < len; i++) {
    			if (i == 3 || i == 6) {
    				seletedX = seletedSpacing;
    				seletedY += selectedBitmapDiameter + seletedSpacing;
    				defaultX = seletedX + selectedBitmapRadius
    						- defaultBitmapRadius;
    				defaultY += selectedBitmapDiameter + seletedSpacing;
    			}
    			points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);
    			seletedX += selectedBitmapDiameter + seletedSpacing;
    			defaultX += selectedBitmapDiameter + seletedSpacing;
    		}
    	}
    
    	private void initPaint() {
    
    		initLinePaint(linePaint);
    		initTextPaint(textPaint);
    		initWhiteLinePaint(whiteLinePaint);
    
    	}
    
    	private void initTextPaint(Paint paint) {
    		textPaint.setTextSize(30);
    		textPaint.setAntiAlias(true);
    		textPaint.setTypeface(Typeface.MONOSPACE);
    
    	}
    
    	private void initLinePaint(Paint paint) {
    
    		// paint.setColor(Color.GRAY);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		// paint.setStyle(Style.STROKE);
    		paint.setStyle(Style.FILL);
    		paint.setStrokeWidth(10);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    	}
    
    	private void initWhiteLinePaint(Paint paint) {
    		// paint.setColor(Color.WHITE);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		paint.setStrokeWidth(8);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    	}
    
    	private void drawNinePoint(Canvas canvas) {
    		if (startPoint != null) {
    			drawEachLine(canvas, startPoint);
    		}
    
    		for (PointInfo pointInfo : points) {
    			if (pointInfo != null) {
    				if (pointInfo.isSelected()) {
    					canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
    							pointInfo.getSeletedY(), null);
    
    				} else { // zj add else case
    					canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
    							pointInfo.getDefaultY(), null);
    				}
    			}
    		}
    	}
    
    	/**
    	 * @param canvas
    	 * @param point
    	 */
    	private void drawEachLine(Canvas canvas, PointInfo point) {
    		if (point.hasNextId()) {
    			int n = point.getNextId();
    			drawLine(canvas, point.getCenterX(), point.getCenterY(),
    					points[n].getCenterX(), points[n].getCenterY());
    			drawEachLine(canvas, points[n]);
    		}
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 * @param startX
    	 * @param startY
    	 * @param stopX
    	 * @param stopY
    	 */
    	private void drawLine(Canvas canvas, float startX, float startY,
    			float stopX, float stopY) {
    		canvas.drawLine(startX, startY, stopX, stopY, linePaint);
    		canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
    
    	}
    
    	private class PointInfo {
    
    		private int id;
    		private int nextId;
    		private boolean selected;
    		private int defaultX;
    		private int defaultY;
    		private int seletedX;
    		private int seletedY;
    
    		public PointInfo(int id, int defaultX, int defaultY, int seletedX,
    				int seletedY) {
    			this.id = id;
    			this.nextId = id;
    			this.defaultX = defaultX;
    			this.defaultY = defaultY;
    			this.seletedX = seletedX;
    			this.seletedY = seletedY;
    		}
    
    		public boolean isSelected() {
    			return selected;
    		}
    
    		public void setSelected(boolean selected) {
    			this.selected = selected;
    		}
    
    		public int getId() {
    			return id;
    		}
    
    		public int getDefaultX() {
    			return defaultX;
    		}
    
    		public int getDefaultY() {
    			return defaultY;
    		}
    
    		public int getSeletedX() {
    			return seletedX;
    		}
    
    		public int getSeletedY() {
    			return seletedY;
    		}
    
    		public int getCenterX() {
    			return seletedX + selectedBitmapRadius;
    		}
    
    		public int getCenterY() {
    			return seletedY + selectedBitmapRadius;
    		}
    
    		public boolean hasNextId() {
    			return nextId != id;
    		}
    
    		public int getNextId() {
    			return nextId;
    		}
    
    		public void setNextId(int nextId) {
    			this.nextId = nextId;
    		}
    
    		/**
    		 * @param x
    		 * @param y
    		 */
    		public boolean isInMyPlace(int x, int y) {
    			boolean inX = x > seletedX
    					&& x < (seletedX + selectedBitmapDiameter);
    			boolean inY = y > seletedY
    					&& y < (seletedY + selectedBitmapDiameter);
    
    			return (inX && inY);
    		}
    
    	}
    
    	public String getPwd() {
    		return lockString.toString();
    
    	}
    
    	public void savePwd() {
    		Intent intent = new Intent();
    		SharedPreferences shareDate = ctx.getSharedPreferences("GUE_PWD", 0);
    
    		String pwd = this.getPwd();
    		String first_pwd = shareDate.getString("GUE_PWD", "HAVE NO PWD");
    		if (pwd.equals(first_pwd)) {
    			// shareDate.edit().clear().commit();
    			// shareDate.edit().putBoolean("IS_SET", true).commit();
    			// shareDate.edit().putString("GUE_PWD", pwd).commit();
    			intent.setClass(ctx, MmsLockList.class);
    		} else {
    			// shareDate.edit().putBoolean("SECOND_ERROR", true).commit();
    			intent.setClass(ctx, MmsLock.class);
    		}
    		ctx.startActivity(intent);
    		((Activity) ctx).finish();
    
    	}
    
    }
    

    到这儿核心功能都贴出来了,布局和资源还有项目代码等以后分离出独立工程的时候附加在后边。

    有疑问欢迎交流。





    转载请注明出处:周木水的CSDN博客 http://blog.csdn.net/zhoumushui

    我的GitHub:周木水的GitHub https://github.com/zhoumushui


    洗衣机坏了,有时候按一会儿就可以启动了,今天怎么弄都没效果,大概是启动电容的问题吧,悲剧。

    下午去看公司部门间的球赛,我们队再胜一局,维持不败战绩,作为拉拉队员还是很开心的。

    今天接着昨天的内容开始~

    哎呀,代码在公司,明天再补充。先去学习。


    Mms类:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    public class MmsLockMsg {
    
    	int _id;
    	int thread_id; // 号码区分标识
    	long address; // 号码
    	long date; // 日期
    	int type;//信息类型
    	// long date_sent; // 发送日期
    	String body; // 短信内容
    	String name;
    
    	public MmsLockMsg(int id, int thread_id, long address, long date,int type,String body,String name) {
    		this._id = id;
    		this.thread_id = thread_id;
    		this.address = address;
    		this.date = date;
    		this.type =type;
    		this.body = body;
    		this.name = name;
    	}
    	public MmsLockMsg(int thread_id, long address, long date,int type, String body,String name) {
    		this.thread_id = thread_id;
    		this.address = address;
    		this.date = date;
    		this.type =type;
    		this.body = body;
    		this.name = name;
    	}
    	
    
    	public int getId() {
    		return _id;
    	}
    
    	public int getThreadId() {
    		return thread_id;
    	}
    
    	public void setThreadId(int thread_id) {
    		this.thread_id = thread_id;
    	}
    
    	public long getAddress() {
    		return address;
    	}
    
    	public void setAddress(long address) {
    		this.address = address;
    	}
    
    	public long getDate() {
    		return date;
    	}
    
    	public void setDate(long date) {
    		this.date = date;
    	}
    	public int getType(){
    		return type;
    	}
    	public void setType(int type){
    		this.type=type;
    	}
    
    	public String getBody() {
    		return body;
    	}
    
    	public void setBody(String body) {
    		this.body = body;
    	}
    	public String getName(){
    		return name;
    	}
    	public void setName(String name){
    		this.name = name;
    	}
    
    }
    


    设置手势密码页:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.graphics.Typeface;
    import android.graphics.Paint.Cap;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    public class MmsLockSetPwd extends View {
    	TextView tv_forget_pwd = (TextView)findViewById(com.android.mms.R.id.zj_lock_forget_pwd);
    	Paint linePaint = new Paint();
    	Paint whiteLinePaint = new Paint();
    	Paint textPaint = new Paint();
    	Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.lock);
    	int defaultBitmapRadius = defaultBitmap.getWidth() / 2;
    	Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.indicator_lock_area);
    	int selectedBitmapDiameter = selectedBitmap.getWidth();
    	int selectedBitmapRadius = selectedBitmapDiameter / 2;
    	PointInfo[] points = new PointInfo[9];
    	PointInfo startPoint = null;
    	int width, height;
    	int moveX, moveY;
    	boolean isUp = false;
    	Context ctx;
    	StringBuffer lockString = new StringBuffer();
    
    	public MmsLockSetPwd(Context context) {
    		
    
    		super(context);
    		ctx = context;
    		// this.setBackgroundColor(Color.WHITE);
    		initPaint();
    	}
    
    	public MmsLockSetPwd(Context context, AttributeSet attrs) {
    
    		super(context, attrs);
    
    		// this.setBackgroundColor(Color.WHITE);
    		tv_forget_pwd.setVisibility(View.GONE); //zj add 
    
    
    		initPaint();
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
    		width = getWidth();
    		height = getHeight();
    		if (width != 0 && height != 0) {
    			initPoints(points);
    		}
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int left, int top, int right,
    			int bottom) {
    		super.onLayout(changed, left, top, right, bottom);
    	}
    	private int startX = 0, startY = 0;
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		// canvas.drawText("passwd:" + lockString, 0, 40, textPaint);
    
    		if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
    			// drawLine(canvas, startX, startY, moveX, moveY);
    		}
    		drawNinePoint(canvas);
    		super.onDraw(canvas);
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    
    		boolean flag = true;
    
    		if (isUp) {
    			finishDraw();
    			flag = false;
    		} else {
    			handlingEvent(event);
    			flag = true;
    		}
    		return flag;
    	}
    
    	private void handlingEvent(MotionEvent event) {
    
    		switch (event.getAction()) {
    
    		case MotionEvent.ACTION_MOVE:
    			moveX = (int) event.getX();
    			moveY = (int) event.getY();
    			for (PointInfo temp : points) {
    				if (temp.isInMyPlace(moveX, moveY)
    						&& temp.isSelected() == false) {
    					temp.setSelected(true);
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					int len = lockString.length();
    					if (len != 0) {
    						int preId = lockString.charAt(len - 1) - 48;
    						points[preId].setNextId(temp.getId());
    					}
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    
    			invalidate(0, height - width, width, height);
    
    			break;
    
    		case MotionEvent.ACTION_DOWN:
    
    			int downX = (int) event.getX();
    			int downY = (int) event.getY();
    			for (PointInfo temp : points) {
    
    				if (temp.isInMyPlace(downX, downY)) {
    
    					temp.setSelected(true);
    					startPoint = temp;
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    
    			invalidate(0, height - width, width, height);
    
    			break;
    
    		case MotionEvent.ACTION_UP:
    
    			startX = startY = moveX = moveY = 0;
    			isUp = true;
    			invalidate();
    			savePwd();
    			break;
    		default:
    			break;
    		}
    	}
    
    	private void finishDraw() {
    
    		for (PointInfo temp : points) {
    			temp.setSelected(false);
    			temp.setNextId(temp.getId());
    		}
    
    		lockString.delete(0, lockString.length());
    		isUp = false;
    		invalidate();
    	}
    
    	private void initPoints(PointInfo[] points) {
    
    		int len = points.length;
    		int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;
    		int seletedX = seletedSpacing;
    		int seletedY = height - width + seletedSpacing;
    		int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
    		int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;
    
    		for (int i = 0; i < len; i++) {
    
    			if (i == 3 || i == 6) {
    
    				seletedX = seletedSpacing;
    				seletedY += selectedBitmapDiameter + seletedSpacing;
    				defaultX = seletedX + selectedBitmapRadius
    						- defaultBitmapRadius;
    				defaultY += selectedBitmapDiameter + seletedSpacing;
    
    			}
    
    			points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);
    			seletedX += selectedBitmapDiameter + seletedSpacing;
    			defaultX += selectedBitmapDiameter + seletedSpacing;
    
    		}
    	}
    
    	private void initPaint() {
    
    		initLinePaint(linePaint);
    		initTextPaint(textPaint);
    		initWhiteLinePaint(whiteLinePaint);
    
    	}
    
    	/**
    	 * @param paint
    	 */
    	private void initTextPaint(Paint paint) {
    
    		textPaint.setTextSize(30);
    		textPaint.setAntiAlias(true);
    		textPaint.setTypeface(Typeface.MONOSPACE);
    
    	}
    
    	/**
    	 * @param paint
    	 */
    	private void initLinePaint(Paint paint) {
    
    		//paint.setColor(Color.GRAY);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		//paint.setStyle(Style.STROKE);
    		paint.setStyle(Style.FILL);
    		
    		paint.setStrokeWidth(10);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    
    	}
    
    	/**
    	 * @param paint
    	 */
    	private void initWhiteLinePaint(Paint paint) {
    		//paint.setColor(Color.WHITE);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		paint.setStrokeWidth(8);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 */
    	private void drawNinePoint(Canvas canvas) {
    
    		if (startPoint != null) {
    			drawEachLine(canvas, startPoint);
    
    		}
    
    		for (PointInfo pointInfo : points) {
    			if (pointInfo != null) {
    				if (pointInfo.isSelected()) {
    					canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
    							pointInfo.getSeletedY(), null);
    				}else{	// zj add
    				canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
    						pointInfo.getDefaultY(), null);
    				}
    			}
    		}
    
    	}
    
    	/**
    	 * @param canvas
    	 * @param point
    	 */
    	private void drawEachLine(Canvas canvas, PointInfo point) {
    		if (point.hasNextId()) {
    			int n = point.getNextId();
    			drawLine(canvas, point.getCenterX(), point.getCenterY(),
    					points[n].getCenterX(), points[n].getCenterY());
    			drawEachLine(canvas, points[n]);
    		}
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 * @param startX
    	 * @param startY
    	 * @param stopX
    	 * @param stopY
    	 */
    	private void drawLine(Canvas canvas, float startX, float startY,
    			float stopX, float stopY) {
    		canvas.drawLine(startX, startY, stopX, stopY, linePaint);
    		canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
    	}
    
    	/**
    	 * @author zkwlx
    	 * 
    	 */
    	private class PointInfo {
    
    		private int id;
    		private int nextId;
    		private boolean selected;
    		private int defaultX;
    		private int defaultY;
    		private int seletedX;
    		private int seletedY;
    
    		public PointInfo(int id, int defaultX, int defaultY, int seletedX,
    				int seletedY) {
    			this.id = id;
    			this.nextId = id;
    			this.defaultX = defaultX;
    			this.defaultY = defaultY;
    			this.seletedX = seletedX;
    			this.seletedY = seletedY;
    		}
    
    		public boolean isSelected() {
    			return selected;
    		}
    
    		public void setSelected(boolean selected) {
    			this.selected = selected;
    		}
    
    		public int getId() {
    			return id;
    		}
    
    		public int getDefaultX() {
    			return defaultX;
    		}
    
    		public int getDefaultY() {
    			return defaultY;
    		}
    
    		public int getSeletedX() {
    			return seletedX;
    		}
    
    		public int getSeletedY() {
    			return seletedY;
    		}
    
    		public int getCenterX() {
    			return seletedX + selectedBitmapRadius;
    		}
    
    		public int getCenterY() {
    			return seletedY + selectedBitmapRadius;
    		}
    
    		public boolean hasNextId() {
    			return nextId != id;
    		}
    
    		public int getNextId() {
    			return nextId;
    		}
    
    		public void setNextId(int nextId) {
    			this.nextId = nextId;
    		}
    
    		/**
    		 * @param x
    		 * @param y
    		 */
    		public boolean isInMyPlace(int x, int y) {
    			boolean inX = x > seletedX
    					&& x < (seletedX + selectedBitmapDiameter);
    			boolean inY = y > seletedY
    					&& y < (seletedY + selectedBitmapDiameter);
    			return (inX && inY);
    		}
    
    	}
    
    	public String getPwd() {
    		return lockString.toString();
    
    	}
    
    	public void savePwd() {
    		Intent intent = new Intent();
    		SharedPreferences shareDate = ctx.getSharedPreferences("GUE_PWD", 0);
    		boolean isSetFirst = shareDate.getBoolean("IS_SET_FIRST", false);
    		if (isSetFirst) {
    			String pwd = this.getPwd();
    			String first_pwd = shareDate.getString("FIRST_PWD", "HAVE NO PWD");
    			if (pwd.equals(first_pwd)) {
    				shareDate.edit().clear().commit();
    				shareDate.edit().putBoolean("IS_SET", true).commit();
    				shareDate.edit().putString("GUE_PWD", pwd).commit();
    				intent.setClass(ctx, MmsLockSetPwdOk.class);
    			} else {
    				shareDate.edit().putBoolean("SECOND_ERROR", true).commit();
    				intent.setClass(ctx, MmsLock.class);
    			}
    		} else {
    			shareDate.edit().clear().commit();
    			shareDate.edit().putString("FIRST_PWD", this.getPwd()).commit();
    			shareDate.edit().putBoolean("IS_SET_FIRST", true).commit();
    			intent.setClass(ctx, MmsLock.class);
    		}
    
    		ctx.startActivity(intent);
    
    		((Activity) ctx).finish();
    
    	}
    
    
    }
    

    手势密码设置成功后,让用户输入字符密保,以防遗忘手势密码:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import android.app.Activity;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.os.Bundle;
    import android.view.View;
    import android.view.Window;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MmsLockSetPwdOk extends Activity {
    	
    	//private TextView showInfo;
    	private EditText secondPwd;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		super.onCreate(savedInstanceState);		
    		//this.requestWindowFeature(Window.FEATURE_NO_TITLE);		
    		setContentView(com.android.mms.R.layout.mms_lock_res);		
    		//showInfo = (TextView)findViewById(com.android.mms.R.id.res_info);	
    
    		//SharedPreferences shareDate = getSharedPreferences("GUE_PWD", 0);	
    		//String pwd = shareDate.getString("GUE_PWD", "HAVE NO PWD !");
    		
    //		showInfo.setText("密码是: "+pwd);
    		//showInfo.setText(com.android.mms.R.string.zj_set_pwd_tip);
    	}
    	
    	public void saveSecondPwd(View v){
    		secondPwd = (EditText)findViewById(com.android.mms.R.id.second_pwd);
    		String secondStr = secondPwd.getText().toString();
    		if(secondStr!= null && secondStr.trim().length() != 0){
            //获取SharedPreferences对象
           // Context ctx = MainActivity.this;       
            SharedPreferences secondShare = getSharedPreferences("SECOND_PWD", MODE_PRIVATE);
            //存入数据
            Editor editor = secondShare.edit();
            editor.putString("SECOND_KEY", secondStr);
            editor.putBoolean("SECOND_IS_SET", true);
            editor.commit();
            Toast.makeText(this, com.android.mms.R.string.zj_set_pwd_success, Toast.LENGTH_SHORT).show();
            finish();
    		}else{
    			Toast.makeText(this, com.android.mms.R.string.zj_pwd_null, Toast.LENGTH_SHORT).show();
    		}
    	}
    }
    



    MmsLockCheckPwd.java:

    /*
     * ZJ add for Mms Lock
     */
    package com.android.mms.ui;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.graphics.Paint.Cap;
    import android.graphics.Paint.Style;
    //import android.os.Vibrator; // zj Cancel 
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    public class MmsLockCheckPwd extends View {
    	TextView tv_forget_pwd = (TextView) findViewById(com.android.mms.R.id.zj_lock_forget_pwd);
    
    	Paint linePaint = new Paint();
    	Paint whiteLinePaint = new Paint();
    	Paint textPaint = new Paint();
    	Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.lock);
    	int defaultBitmapRadius = defaultBitmap.getWidth() / 2;
    	Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
    			com.android.mms.R.drawable.indicator_lock_area);
    	int selectedBitmapDiameter = selectedBitmap.getWidth();
    	int selectedBitmapRadius = selectedBitmapDiameter / 2;
    	PointInfo[] points = new PointInfo[9];
    	PointInfo startPoint = null;
    	int width, height;
    	int moveX, moveY;
    	boolean isUp = false;
    	Context ctx;
    	StringBuffer lockString = new StringBuffer();
    
    	public MmsLockCheckPwd(Context context) {
    
    		super(context);
    		ctx = context;
    		// this.setBackgroundColor(Color.WHITE);
    		initPaint();
    	}
    
    	public MmsLockCheckPwd(Context context, AttributeSet attrs) {
    		super(context, attrs);
    
    		// this.setBackgroundColor(Color.WHITE);
    		tv_forget_pwd.setVisibility(View.VISIBLE); // zj add
    		initPaint();
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		width = getWidth();
    		height = getHeight();
    		if (width != 0 && height != 0) {
    			initPoints(points);
    		}
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int left, int top, int right,
    			int bottom) {
    		super.onLayout(changed, left, top, right, bottom);
    	}
    
    	private int startX = 0, startY = 0;
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    
    		// canvas.drawText("passwd:" + lockString, 0, 40, textPaint);
    		if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
    			// drawLine(canvas, startX, startY, moveX, moveY);
    		}
    		drawNinePoint(canvas);
    		super.onDraw(canvas);
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    
    		boolean flag = true;
    		if (isUp) {
    			finishDraw();
    			flag = false;
    		} else {
    			handlingEvent(event);
    			flag = true;
    		}
    		return flag;
    	}
    
    	private void handlingEvent(MotionEvent event) {
    
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_MOVE:
    			moveX = (int) event.getX();
    			moveY = (int) event.getY();
    			for (PointInfo temp : points) {
    				if (temp.isInMyPlace(moveX, moveY)
    						&& temp.isSelected() == false) {
    					temp.setSelected(true);
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					int len = lockString.length();
    					if (len != 0) {
    						int preId = lockString.charAt(len - 1) - 48;
    						points[preId].setNextId(temp.getId());
    					}
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    			invalidate(0, height - width, width, height);
    			break;
    
    		case MotionEvent.ACTION_DOWN:
    
    			int downX = (int) event.getX();
    			int downY = (int) event.getY();
    			for (PointInfo temp : points) {
    				if (temp.isInMyPlace(downX, downY)) {
    					temp.setSelected(true);
    					startPoint = temp;
    					startX = temp.getCenterX();
    					startY = temp.getCenterY();
    					lockString.append(temp.getId());
    					break;
    				}
    			}
    			invalidate(0, height - width, width, height);
    			break;
    
    		case MotionEvent.ACTION_UP:
    			startX = startY = moveX = moveY = 0;
    			isUp = true;
    			invalidate();
    			savePwd();
    			break;
    		default:
    			break;
    		}
    	}
    
    	private void finishDraw() {
    		for (PointInfo temp : points) {
    			temp.setSelected(false);
    			temp.setNextId(temp.getId());
    		}
    		lockString.delete(0, lockString.length());
    		isUp = false;
    		invalidate();
    	}
    
    	private void initPoints(PointInfo[] points) {
    
    		int len = points.length;
    		int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;
    		int seletedX = seletedSpacing;
    		int seletedY = height - width + seletedSpacing;
    		int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
    		int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;
    
    		for (int i = 0; i < len; i++) {
    			if (i == 3 || i == 6) {
    				seletedX = seletedSpacing;
    				seletedY += selectedBitmapDiameter + seletedSpacing;
    				defaultX = seletedX + selectedBitmapRadius
    						- defaultBitmapRadius;
    				defaultY += selectedBitmapDiameter + seletedSpacing;
    			}
    			points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);
    			seletedX += selectedBitmapDiameter + seletedSpacing;
    			defaultX += selectedBitmapDiameter + seletedSpacing;
    		}
    	}
    
    	private void initPaint() {
    
    		initLinePaint(linePaint);
    		initTextPaint(textPaint);
    		initWhiteLinePaint(whiteLinePaint);
    
    	}
    
    	private void initTextPaint(Paint paint) {
    		textPaint.setTextSize(30);
    		textPaint.setAntiAlias(true);
    		textPaint.setTypeface(Typeface.MONOSPACE);
    
    	}
    
    	private void initLinePaint(Paint paint) {
    
    		// paint.setColor(Color.GRAY);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		// paint.setStyle(Style.STROKE);
    		paint.setStyle(Style.FILL);
    		paint.setStrokeWidth(10);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    	}
    
    	private void initWhiteLinePaint(Paint paint) {
    		// paint.setColor(Color.WHITE);
    		paint.setColor(Color.parseColor("#1E90FF"));
    		paint.setStrokeWidth(8);
    		paint.setAntiAlias(true);
    		paint.setStrokeCap(Cap.ROUND);
    	}
    
    	private void drawNinePoint(Canvas canvas) {
    		if (startPoint != null) {
    			drawEachLine(canvas, startPoint);
    		}
    
    		for (PointInfo pointInfo : points) {
    			if (pointInfo != null) {
    				if (pointInfo.isSelected()) {
    					canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
    							pointInfo.getSeletedY(), null);
    
    				} else { // zj add else case
    					canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
    							pointInfo.getDefaultY(), null);
    				}
    			}
    		}
    	}
    
    	/**
    	 * @param canvas
    	 * @param point
    	 */
    	private void drawEachLine(Canvas canvas, PointInfo point) {
    		if (point.hasNextId()) {
    			int n = point.getNextId();
    			drawLine(canvas, point.getCenterX(), point.getCenterY(),
    					points[n].getCenterX(), points[n].getCenterY());
    			drawEachLine(canvas, points[n]);
    		}
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 * @param startX
    	 * @param startY
    	 * @param stopX
    	 * @param stopY
    	 */
    	private void drawLine(Canvas canvas, float startX, float startY,
    			float stopX, float stopY) {
    		canvas.drawLine(startX, startY, stopX, stopY, linePaint);
    		canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
    
    	}
    
    	private class PointInfo {
    
    		private int id;
    		private int nextId;
    		private boolean selected;
    		private int defaultX;
    		private int defaultY;
    		private int seletedX;
    		private int seletedY;
    
    		public PointInfo(int id, int defaultX, int defaultY, int seletedX,
    				int seletedY) {
    			this.id = id;
    			this.nextId = id;
    			this.defaultX = defaultX;
    			this.defaultY = defaultY;
    			this.seletedX = seletedX;
    			this.seletedY = seletedY;
    		}
    
    		public boolean isSelected() {
    			return selected;
    		}
    
    		public void setSelected(boolean selected) {
    			this.selected = selected;
    		}
    
    		public int getId() {
    			return id;
    		}
    
    		public int getDefaultX() {
    			return defaultX;
    		}
    
    		public int getDefaultY() {
    			return defaultY;
    		}
    
    		public int getSeletedX() {
    			return seletedX;
    		}
    
    		public int getSeletedY() {
    			return seletedY;
    		}
    
    		public int getCenterX() {
    			return seletedX + selectedBitmapRadius;
    		}
    
    		public int getCenterY() {
    			return seletedY + selectedBitmapRadius;
    		}
    
    		public boolean hasNextId() {
    			return nextId != id;
    		}
    
    		public int getNextId() {
    			return nextId;
    		}
    
    		public void setNextId(int nextId) {
    			this.nextId = nextId;
    		}
    
    		/**
    		 * @param x
    		 * @param y
    		 */
    		public boolean isInMyPlace(int x, int y) {
    			boolean inX = x > seletedX
    					&& x < (seletedX + selectedBitmapDiameter);
    			boolean inY = y > seletedY
    					&& y < (seletedY + selectedBitmapDiameter);
    
    			return (inX && inY);
    		}
    
    	}
    
    	public String getPwd() {
    		return lockString.toString();
    
    	}
    
    	public void savePwd() {
    		Intent intent = new Intent();
    		SharedPreferences shareDate = ctx.getSharedPreferences("GUE_PWD", 0);
    
    		String pwd = this.getPwd();
    		String first_pwd = shareDate.getString("GUE_PWD", "HAVE NO PWD");
    		if (pwd.equals(first_pwd)) {
    			// shareDate.edit().clear().commit();
    			// shareDate.edit().putBoolean("IS_SET", true).commit();
    			// shareDate.edit().putString("GUE_PWD", pwd).commit();
    			intent.setClass(ctx, MmsLockList.class);
    		} else {
    			// shareDate.edit().putBoolean("SECOND_ERROR", true).commit();
    			intent.setClass(ctx, MmsLock.class);
    		}
    		ctx.startActivity(intent);
    		((Activity) ctx).finish();
    
    	}
    
    }
    

    到这儿核心功能都贴出来了,布局和资源还有项目代码等以后分离出独立工程的时候附加在后边。

    有疑问欢迎交流。



    2.联系人实现字母条定位和长按多选操作

    这也是仿造微信电话本项目的一个部分,主要实现了以下功能:

    * 搜索联系人

    * 联系人列表右侧字母快速定位,收藏联系人显示在列表前端

    * 长按删除多个联系人,群发短信

    * 联系人详情标星收藏,发送名片

    * 编辑/新建联系人可编辑头像,添加多条号码

    贴个效果图:



    下面介绍一下具体功能的对应实现:

    联系人列表长按监听:

    	m_contactslist
    				.setOnItemLongClickListener(new OnItemLongClickListener() {
    
    					@Override
    					public boolean onItemLongClick(AdapterView<?> arg0,
    							View arg1, int arg2, long arg3) {
    
    						multiDeleteContacts();
    						// leftText.setVisibility(View.VISIBLE);
    						// leftText.setText(R.string.action_settings);
    						return true;
    					}
    				});


    搜索编辑框文本改变时的监听器:

    	m_FilterEditText.addTextChangedListener(new TextWatcher() {
    
    			@Override
    			public void onTextChanged(CharSequence s, int start, int before,
    					int count) {
    
    				if (!"".equals(s.toString().trim())) {
    					// 根据编辑框值过滤联系人并更新联系列表
    					FilterSearch(s.toString().trim());
    
    					m_FAdapter = new FilterAdapter(mPeopleActivity.this,
    							mFilterList);
    					m_contactslist.setAdapter(m_FAdapter);
    					m_searchCleanBtn.setVisibility(View.VISIBLE);
    					mAScrollBar.setVisibility(View.GONE);
    					// m_topcontactslayout.setVisibility(View.GONE);
    					// m_bottomcontactslayout.setVisibility(View.VISIBLE);
    				} else {
    					m_contactslist.setAdapter(Utils.m_contactsAdapter);
    					m_topcontactslayout.setVisibility(View.VISIBLE);
    					mAScrollBar.setVisibility(View.VISIBLE);
    					m_searchCleanBtn.setVisibility(View.GONE);
    					// m_bottomcontactslayout.setVisibility(View.VISIBLE);
    				}
    			}
    
    			@Override
    			public void beforeTextChanged(CharSequence s, int start, int count,
    					int after) {
    				// TODO Auto-generated method stub
    			}
    
    			@Override
    			public void afterTextChanged(Editable s) {
    				// TODO Auto-generated method stub
    			}
    		});

    触摸字母的监听器:

    	private class ScrollBarListener implements
    			AlphabetScrollBar.OnTouchBarListener {
    
    		@Override
    		public void onTouch(String letter) {
    
    			// {@ TChip ZJ: 添加标星表
    			if (letter.compareTo("☆") == 0) {
    				m_contactslist.setSelection(0);
    			} else
    			// TChip @}
    			if (letter.compareTo("#") == 0) {
    				// {@ TChip ZJ:跳转到列表最后位置 @}
    				int zjCount = m_contactslist.getCount();
    				m_contactslist.setSelection(zjCount);
    			} else {
    				// 触摸字母列时,将联系人列表更新到首字母出现的位置
    				int idx = Utils.binarySearch(letter);
    				if (idx != -1) {
    					m_contactslist.setSelection(idx);
    				}
    			}
    		}
    	}

    长按多选删除的实现:

    private class DeleteContactsTask extends AsyncTask<Void, Integer, Void> {
    
    		@Override
    		protected Void doInBackground(Void... params) {
    			ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    
    			for (int i = 0; i < ChooseContactsID.size(); i++) {
    				ops.add(ContentProviderOperation.newDelete(
    						Uri.withAppendedPath(RawContacts.CONTENT_URI,
    								ChooseContactsID.get(i))).build());
    				// ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
    				// .withSelection(Data.RAW_CONTACT_ID + "=?", new
    				// String[]{ChooseContactsID.get(i)})
    				// .build());
    			}
    
    			try {
    				getContentResolver()
    						.applyBatch(ContactsContract.AUTHORITY, ops);
    			} catch (RemoteException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			} catch (OperationApplicationException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			return null;
    		}
    
    		@Override
    		protected void onPostExecute(Void result) {
    			if (m_dialogLoading != null) {
    				m_dialogLoading.dismiss();
    				finish();
    			}
    		}
    
    		@Override
    		protected void onPreExecute() {
    			m_dialogLoading = new ProgressDialog(MultiDeleteActivity.this);
    			m_dialogLoading.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 设置风格为圆形进度条
    			m_dialogLoading.setMessage("正在删除");
    			m_dialogLoading.setCancelable(false);
    			m_dialogLoading.show();
    		}
    
    		@Override
    		protected void onProgressUpdate(Integer... values) {
    		}
    
    	}

    长按多选群发短信的实现:

    private class MultiSmsTask extends AsyncTask<Void, Integer, Void> {
    
    		@Override
    		protected Void doInBackground(Void... params) {
    			ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    
    			for (int i = 0; i < ChooseContactsID.size(); i++) {
    				// ops.add(ContentProviderOperation.newDelete(Uri.withAppendedPath(RawContacts.CONTENT_URI,
    				// ChooseContactsID.get(i))).build());
    				String contactId = ChooseContactsID.get(i);
    
    				zjSmsNum = zjSmsNum + getNumByContactId(contactId) + ";";
    			}
    			Log.e("zj", "zjSmsNum:" + zjSmsNum + "   ZJSmsCount:"
    					+ ChooseContactsID.size());
    			//
    			Uri uri = Uri.parse("smsto:" + zjSmsNum);
    			Intent it = new Intent(Intent.ACTION_SENDTO, uri);
    			startActivity(it);
    			/*
    			 * try { getContentResolver()
    			 * .applyBatch(ContactsContract.AUTHORITY, ops);
    			 * //Log.e("ZJSmsCount", "" + ChooseContactsID.size()); } catch
    			 * (RemoteException e) { // TODO Auto-generated catch block
    			 * e.printStackTrace(); } catch (OperationApplicationException e) {
    			 * // TODO Auto-generated catch block e.printStackTrace(); }
    			 */
    
    			return null;
    		}
    
    		@Override
    		protected void onPostExecute(Void result) {
    			if (m_dialogLoading != null) {
    				m_dialogLoading.dismiss();
    				finish();
    			}
    		}
    
    		@Override
    		protected void onPreExecute() {
    			m_dialogLoading = new ProgressDialog(MultiDeleteActivity.this);
    			m_dialogLoading.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 设置风格为圆形进度条
    			m_dialogLoading.setMessage("正在发送");
    			m_dialogLoading.setCancelable(false);
    			m_dialogLoading.show();
    		}
    
    		@Override
    		protected void onProgressUpdate(Integer... values) {
    		}
    
    	}


    好了,准备去吃饭了,先到这里吧。




    2. 联系人实现字母条定位和长按多选操作
    展开全文
  • 注意:本项目基于android studio开发,eclipse可能无法直接导入。 demo功能: 1、可以发送短信并且加密(通过改变string中的char) 2、能够查看手机中的短信 3、能够给收到的加密短信解密。 涉及到的知识点: ...
  • android 应用加密 重点 (Top highlight)In this tutorial, we’ll build an encrypted chat/messaging example app for Android. To do this, we will combine both Stream Chat and Virgil Security platforms. ...

    android 应用加密

    重点 (Top highlight)

    In this tutorial, we’ll build an encrypted chat/messaging example app for Android. To do this, we will combine both Stream Chat and Virgil Security platforms. Stream and Virgil make it easy to build a solution with excellent security by combining all of the features you would expect as a developer when creating a messaging app.

    在本教程中,我们将为Android构建一个加密的聊天/消息示例应用程序。 为此,我们将结合Stream ChatVirgil Security平台。 通过结合使用您在创建消息传递应用程序时作为开发人员的所有期望功能,Stream和Virgil可以轻松构建具有出色安全性的解决方案。

    These two services allow developers to integrate chat that is zero knowledge to your backend or Stream. The example app embeds Virgil Security’s eThree Kit — a secure encrypted messaging platform — with Stream Chat’s Android components.

    这两项服务使开发人员可以将对您零知识的聊天集成到您的后端或流中。 示例应用程序嵌入 维吉尔安全 eThree套件 —安全的加密消息传递平台 -使用Stream Chat的Android组件。

    Note that all source code for this example, Android app is available on GitHub. Additionally, before jumping into this tutorial, I recommend checking out the Stream Chat Android tutorial, which will walk you through how to implement Stream Chat from a high-level overview.

    请注意,此示例Android应用程序的所有源代码都可以在GitHub找到 。 另外,在进入本教程之前,我建议您阅读AndroidStream Chat教程 ,它将从较高的概述中逐步指导您如何实现Stream Chat。

    什么是端到端加密消息? (What Is End-To-End Encrypted Messaging?)

    End-to-end encrypted messaging means that the users within that specific chat can only read messages sent between two people. To enable this, the messages that are sent are encrypted before leaving a user’s device, and can only be decrypted by the intended recipient (end-user).

    端到端加密消息传递意味着特定聊天中的用户只能阅读两个人之间发送的消息。 为此,发送的消息在离开用户设备之前已加密,并且只能由预期的接收者(最终用户)解密。

    Virgil Security is a vendor that allows developers to create end-to-end encryption via public/private key technology through the use of their robust and secure encrypted messaging service. With Virgil’s Android SDK, developers can securely create, store, and provide robust end-to-end encryption.

    Virgil Security是一家供应商,允许开发人员通过使用其健壮且安全的加密消息传递服务,通过公用/专用密钥技术创建端到端加密。 借助Virgil的Android SDK,开发人员可以安全地创建,存储和提供强大的端到端加密。

    During this tutorial, we will learn how to build a Stream Chat app that uses Virgil’s encryption/decryption platform to prevent anyone except the intended parties from reading messages. No one in your company, nor any cloud provider you use, can read these messages. In essence, even if a malicious person gained access to the database containing the messages, that person would only see encrypted text, called ciphertext.

    在本教程中,我们将学习如何构建一个使用Virgil的加密/解密平台的Stream Chat应用程序,以防止除目标用户之外的任何人阅读消息。 您公司中的任何人,或者您使用的任何云提供商,都无法阅读这些消息。 本质上,即使恶意人员获得了访问包含消息的数据库的权限,该人员也只会看到称为密文的加密文本。

    构建加密的聊天消息应用程序 (Building an Encrypted Chat Messaging Application)

    To build this app, we’ll mostly rely on two libraries, Stream Chat Android and Virgil Security for Kotlin. Our outcome will encrypt text on the device before sending a message. Decryption and verification will both happen in the receiver’s device. Stream’s Messaging API will only see ciphertext, ensuring our user’s data is never seen by anyone else, including us.

    要构建此应用,我们将主要依靠两个库,即Stream Chat Android和Virgil Security for Kotlin。 我们的结果将在发送消息之前对设备上的文本进行加密。 解密和验证都将在接收方的设备中进行。 Stream的Messaging API仅能看到密文,以确保包括我们在内的其他任何人都不会看到我们用户的数据。

    To accomplish this, the app performs the following steps:

    为此,该应用程序执行以下步骤:

    1. A user authenticates with your backend.

      用户向您的后端进行身份验证。
    2. The user’s app requests a Stream auth token and API key from the backend. The Android app creates a Stream Chat Client for that user.

      用户的应用程序从后端请求流身份验证令牌和API密钥。 Android应用会为该用户创建一个Stream Chat Client

    3. The user’s app requests a Virgil auth token from the backend and registers with Virgil. This generates their private and public key. The private key is stored locally, and the public key is stored in Virgil.

      用户的应用程序从后端请求Virgil身份验证令牌,并向Virgil注册。 这将生成其私钥和公钥。 私钥存储在本地,而公钥存储在Virgil中。
    4. Once the user decides who they want to chat with the app creates and joins a Stream Chat Channel.

      用户决定要与该应用聊天的对象后,即可创建并加入流聊天频道

    5. The app asks Virgil for the receiver’s public key.

      该应用程序向Virgil询问接收者的公共密钥。
    6. The user types a message and sends it to Stream. Before sending, the app passes the receiver’s public key to Virgil to encrypt the message. The message is relayed through Stream Chat to the receiver. Stream receives ciphertext, meaning they can never see the original message.

      用户键入一条消息并将其发送到Stream。 在发送之前,该应用将接收者的公钥传递给Virgil来加密消息。 该消息通过流聊天中继到接收者。 Stream收到密文,这意味着他们永远看不到原始消息。
    7. The receiving user decrypts the sent message using Virgil. When the message is received, the app decrypts the message using the Virgil and this is passed along to Stream’s UI components. Virgil verifies the message is authentic by using the sender’s public key.

      接收用户使用Virgil解密发送的消息。 收到消息后,应用程序将使用Virgil对消息进行解密,并将消息传递到Stream的UI组件。 Virgil使用发件人的公钥验证邮件的真实性。

    While this looks complicated, Stream and Virgil do most of the work for us. We’ll use Stream’s out of the box UI components to render the chat UI and Virgil to do all of the cryptography and key management. We simply combine these services.

    尽管这看起来很复杂,但Stream和Virgil为我们完成了大部分工作。 我们将使用Stream的现成UI组件来呈现聊天UI,而Virgil将使用所有的加密和密钥管理。 我们只是将这些服务结合在一起。

    The code is split between the Android frontend contained in the android directory, and the Express (Node.js) backend is found in the backend directory. See the README.md in each directory to see installing and running instructions. If you'd like to follow along with running code, make sure you get both the backend and android running before continuing.

    该代码是Android之间的分裂前端包含在android目录,而快递(Node.js的)后端在发现backend目录。 请参阅每个目录中的README.md以查看安装和运行说明。 如果您想继续执行代码,请确保在继续运行之前先运行backendandroid

    Let’s walk through and look at the important code needed for each step.

    让我们来看一下每个步骤所需的重要代码。

    先决条件 (Prerequisites)

    Basic knowledge of Android (Kotlin) and Node.js is required to follow this how-to tutorial.

    要学习此入门指南,需要具备Android(Kotlin)和Node.js的基础知识。

    Note that this secure messaging app is intended only to run locally on your machine, and we will not be covering how to deploy the example app to iOS or Android app stores.

    请注意,此安全消息传递应用程序仅旨在在您的计算机上本地运行,我们将不介绍如何将示例应用程序部署到iOS或Android应用程序商店。

    We use Anko to simplify our asynchronous code. Please note this library was recently deprecated. There are also likely bugs in our async implementation. However, we chose to keep the noise to a minimum in this tutorial by leveraging Anko and keeping async simple. Please use best practices for asynchronous code.

    我们使用Anko来简化异步代码。 请注意,该库最近已弃用 。 我们的异步实现中也可能存在错误。 但是,在本教程中,我们选择通过利用Anko并使异步保持简单来将噪声降至最低。 请对异步代码使用最佳做法。

    You will need an account with Stream and Virgil. Once you’ve created your accounts, you can place your credentials in backend/.env if you'd like to run the code. You can use backend/.env.example as a reference for what credentials are required. You also need to place your Stream API key in MainActivity.kt:60.

    您将需要具有StreamVirgil的帐户。 创建帐户后,如果您想运行代码,则可以将凭据放在backend/.env 。 您可以使用backend/.env.example作为所需凭据的参考。 您还需要将Stream API密钥放在MainActivity.kt:60

    步骤0。设置后端 (Step 0. Setup the Backend)

    For our Android frontend to interact with Stream and Virgil, the application provides three endpoints:

    为了使我们的Android前端与Stream和Virgil进行交互,该应用程序提供了三个端点:

    • POST /v1/authenticate: This endpoint generates an auth token that allows the Android app to communicate with /v1/stream-credentials and /v1/virgil-credentials. To keep things simple, this endpoint allows the client to be any user. The frontend tells the backend who it wants to authenticate as. In your application, this should be replaced with your API's authentication endpoint.

      POST /v1/authenticate :此端点生成一个auth令牌,该令牌允许Android应用与/v1/stream-credentials/v1/virgil-credentials 。 为简单起见,此端点允许客户端成为任何用户。 前端告诉后端它想作为谁进行身份验证。 在您的应用程序中,应将其替换为您API的身份验证端点。

    • POST /v1/stream-credentials: This returns the data required for the Android app to communicate with Stream. In order return this info we need to tell Stream this user exists and ask them to create a valid auth token:

      POST /v1/stream-credentials :这将返回Android应用程序与Stream通信所需的数据。 为了返回此信息,我们需要告诉Stream该用户存在,并要求他们创建有效的身份验证令牌:

    The response payload has this shape:

    响应有效负载具有以下形状:

    • apiKey is the stream account identifier for your Stream instance. Needed to identify what account your frontend is trying to connect with.

      apiKey是您的Stream实例的流帐户标识符。 需要确定您的前端试图连接哪个帐户。

    • token JWT token to authorize the frontend with Stream.

      token JWT令牌,用于使用Stream授权前端。

    • user: This object contains the data that the frontend needs to connect and render the user's view.

      user :此对象包含前端连接和呈现用户视图所需的数据。

    • POST /v1/virgil-credentials: This returns the authentication token used to connect the frontend to Virgil. We use the Virgil Crypto SDK to generate a valid auth token for us:

      POST /v1/virgil-credentials :这将返回用于将前端连接到Virgil的身份验证令牌。 我们使用Virgil Crypto SDK为我们生成有效的身份验证令牌:

    In this case, the frontend only needs the auth token.

    在这种情况下,前端只需要auth令牌。

    步骤1.用户通过后端进行身份验证 (Step 1. User Authenticates With Backend)

    First, we log in to a user. To keep things simple we’ll just have an empty form that lets you log in with any name:

    首先,我们登录到用户。 为简单起见,我们将使用一个空表格来使用任何名称登录:

    Image for post

    This is a simple form that takes any arbitrary name, effectively allowing us to log in as anyone. We set this up in our MainActivity:

    这是一种简单的形式,可以使用任意名称,有效地允许我们以任何人身份登录。 我们在MainActivity

    And the layout:

    以及布局:

    When we submit the form, we sign into our backend, get a Stream and Virgil frontend auth token, generate our private key, and register with Virgil, then start our next activity. We’ll look at each of these in turn.

    提交表单时,我们登录到后端,获取Stream和Virgil前端身份验证令牌,生成私钥,并在Virgil中注册,然后开始下一个活动。 我们将依次研究每个。

    Let’s see our sign in and token generation:

    让我们看看我们的登录和令牌生成:

    Since our backend (see Step 1) does the token generation, these are simple REST calls. The tokens returned are frontend auth tokens, which allow our client to talk to Stream and Virgil directly. Besides returning a list of users, we no longer need our backend to do any work.

    由于我们的backend (请参阅步骤1)执行令牌生成,因此这些都是简单的REST调用。 返回的令牌是前端身份验证令牌,使我们的客户端可以直接与Stream和Virgil进行对话。 除了返回用户列表之外,我们不再需要后端进行任何工作。

    Now that we have our frontend tokens, let’s generate our private keys and register our public keys with Virgil:

    现在我们有了前端令牌,让我们生成私有密钥并向Virgil注册我们的公共密钥:

    Virgil’s client is called eThree. We initialize an EThree instance and register. This call generates a private key and stores it on the device and sends our public key to Virgil. If we get a RegistrationException, we have already registered this user. Keep in mind, and you cannot log into the same user on a different device since we're not sharing the private key with the other device! This is possible, but out of scope for this tutorial. If you'd like to accomplish this, see Virgil's documentation.

    Virgil的客户称为eThree 。 我们初始化一个EThree实例并注册。 该调用将生成一个私钥并将其存储在设备上,并将我们的公钥发送给Virgil。 如果收到RegistrationException ,则我们已经注册了该用户。 请注意,由于我们不与其他设备共享私钥,因此您无法在其他设备上登录同一用户! 这是可能的,但是超出了本教程的范围。 如果您想完成此操作,请参阅Virgil的文档

    Now that we have our tokens and registration let’s find a user to chat with!

    现在我们有了令牌和注册,让我们找到一个可以聊天的用户!

    步骤2:列出使用者 (Step 2: List users)

    To keep things simple, we’ll get all registered users from our backend and display them in a simple list view:

    为简单起见,我们将从后端获取所有注册用户,并将其显示在简单的列表视图中:

    Image for post

    Here is the activity:

    这是活动:

    And the layout:

    以及布局:

    We make an API call via BackendService.getUsers and filter the logged-in user out. We add the response to a simple ArrayAdapter and display our results in a ListView. When a user clicks on a list item, we start a ChannelActivity, which is a 1:1 chat channel.

    我们通过BackendService.getUsers进行API调用,并过滤掉登录的用户。 我们将响应添加到简单的ArrayAdapter并将结果显示在ListView 。 当用户单击列表项时,我们将启动ChannelActivity ,这是一个1:1聊天频道。

    步骤3:建立私人1:1频道 (Step 3: Create a Private 1:1 Channel)

    First, we need to create our channel for our private chat. Let’s look at our activity and layout:

    首先,我们需要为我们的私人聊天创建频道。 让我们看看我们的活动和布局:

    And the layout:

    以及布局:

    We use off the shelf Stream UI components with two slight variations. First, we hook in a custom EncryptedMessageInputView, which allows us to encrypt a message before sending it. We also hook in a custom EncryptedMessageViewHolderFactory, which allows message decryption (we'll look at this in a bit). The essential bits start inside of doAsync. First, we look up the other user's public key. This let's use encrypt our messages and verify their messages are authentic. Next, we create a channel in Stream via .query. Once then channel is created, we load messages. Before we look at how we load messages, we need to send a message first.

    我们使用现成的Stream UI组件有两个微小的变化。 首先,我们挂钩一个自定义的EncryptedMessageInputView ,它允许我们在发送消息之前对其进行加密。 我们还挂钩了一个自定义的EncryptedMessageViewHolderFactory ,它允许消息解密(稍后我们将对此进行介绍)。 基本位在doAsync内部开始。 首先,我们查找其他用户的公钥。 让我们使用加密消息并验证其消息是真实的。 接下来,我们通过.query在Stream中创建一个通道。 创建通道后,我们便会加载消息。 在查看如何加载消息之前,我们需要先发送一条消息。

    步骤4:发送加密的消息 (Step 4: Sending an Encrypted Message)

    Let’s look at EncryptedMessageInputView, which is bound in the layout and configured in our activity. Here is the code:

    让我们看一下EncryptedMessageInputView ,它绑定在布局中并在我们的活动中配置。 这是代码:

    We override Stream’s MessageInputView and simply decrypt the message before sending it. MessageInputView calls prepareMessage before sending it to the API, so we override this and encrypt before sending the message along.

    我们重写Stream的MessageInputView并在发送之前简单地解密消息。 MessageInputView在将其发送到API之前会调用prepareMessage ,因此我们将其覆盖并加密,然后再发送消息。

    Please note that updating a message does not utilize this method, so be aware if you want to support edit functionality. You can consider building your own MessageInputView. For brevity, we won't go there in this tutorial.

    请注意,更新消息不会使用此方法,因此请注意是否要支持编辑功能。 您可以考虑构建自己的MessageInputView 。 为简便起见,本教程中不会去那里。

    步骤5:查看消息 (Step 5: Viewing Messages)

    Since all of our messages in Stream our now ciphertext, we need to decrypt them before displaying. To hook into Stream’s UI components, we bind via binding.messageList.setViewHolderFactory(EncryptedMessageViewHolderFactory(eThree)). With our custom factory, we can initialize a custom decryption object for each message:

    由于我们Stream中的所有消息都是我们现在的密文,因此我们需要在显示之前解密它们。 为了连接到Stream的UI组件,我们通过binding.messageList.setViewHolderFactory(EncryptedMessageViewHolderFactory(eThree))绑定。 使用我们的自定义工厂,我们可以为每条消息初始化一个自定义解密对象:

    This factory checks if we have a message type (vs. another type such as a date separator) and initializes our EncryptedMessageViewHolder. Let's look take a look:

    该工厂检查我们是否具有消息类型(相对于其他类型,例如日期分隔符),并初始化EncryptedMessageViewHolder 。 让我们看一下:

    First, we check if we have a regular message, and if we do, we decrypt it. We copy our message object to avoid mutating the original version (Stream caches this, and we’ll mess things up if we manipulate that). With that copy, we check if the message is ours or theirs. In our case, we know how to decrypt directly since we created it. If it’s theirs, we need to look up their public key to verify the message. We pass this to Virgil and do our decryption.

    首先,我们检查是否有常规消息,如果有,则将其解密。 我们复制消息对象以避免更改原始版本(Stream对此进行缓存,如果对其进行操作,将会使事情搞砸)。 使用该副本,我们检查邮件是我们的还是他们的。 在我们的案例中,自创建以来,我们就知道如何直接解密。 如果是他们的,我们需要查找他们的公钥以验证消息。 我们将此传递给Virgil并进行解密。

    Putting these last steps together, we’ll see our final product:

    将这些最后的步骤放在一起,我们将看到最终产品:

    Image for post

    最后的想法 (Final Thoughts)

    And that’s it. We now have a private and extremely secure end-to-end encrypted messaging app built for Android with Stream Chat and Virgil Security. You should have a full understanding of the basics of end-to-end encryption using Stream Chat and Virgil Security, along with a fundamental understanding of how the E2EE process works when implemented with Android, Virgil, and Stream Chat.

    就是这样。 w ^ e现在拥有一个专用于Android的私有且极其安全的端到端加密消息应用程序,具有 即时通讯 维吉尔安全 您应该全面了解使用Stream Chat和Virgil Security进行的端到端加密的基础知识,以及对在使用Android,Virgil和Stream Chat实施时E2EE流程如何工作的基本理解。

    If you want to take it a step further, Stream Chat offers several resources to help you get to the next level with your Android chops. Check out the links below:

    如果您想更进一步,Stream Chat提供了多种资源来帮助您将Android排行榜提升到一个新的水平。 检查下方的链接:

    Happy coding, and as always, please feel free to drop any thoughts or questions in the comments below.

    祝您编程愉快,并且一如既往,请随时在下面的评论中提出任何想法或问题。

    Originally published on The Stream Blog at https://getstream.io/blog/encrypted-messaging-app-android/.

    最初发布在The Stream Blog上, 网址 https://getstream.io/blog/encrypted-messaging-app-android/

    翻译自: https://medium.com/swlh/encrypted-messaging-app-android-c57f14a180cb

    android 应用加密

    展开全文
  • Android常用加密方式

    千次阅读 2019-05-16 23:56:10
    加密解密简介 加密技术是最常用的安全保密手段,利用技术手段把重要的数据变为乱码(加密)传送,到达目的地后再用相同或不同的手段还原(解密)。加密技术包括两个元素:算法和密钥。算法是将普通的信息或者可以...
  • TextSecure是Whisper Systems(现已经被Twitter收购)出品的一个为Android设备的短信提供加密服务的工具,TextSecure可以使用流量数据(WiFi/3G/4G)或短信进行安全通信,所有TextSecure消息都可以在设备上本地加密,...
  • 适用于 Android加密文本聊天应用程序由 Weston Mossman 编写 Android 代码由 Benjamin Gordon 编写 Google AppEngine 服务器 OTR 加密库由 Justin Tracey 实现 最初的动机是与 Luca De Alfaro 的 UCSC 移动应用...
  • 加密短信源码

    2021-03-16 16:44:26
    加密短信源码TextSecure是Whisper Systems(现已经被Twitter收购)出品的一个为Android设备的短信提供加密服务的工具,TextSecure可以使用流量数据(WiFi/3G/4G)或短信进行安全通信,所有TextSecure消息都可以在设备...
  • 基于轻量级加密算法的手机短信加密软件.pdf
  • TextSecure是Whisper Systems(现已经被Twitter收购)出品的一个为Android设备的短信提供加密服务的工具,TextSecure可以使用流量数据(WiFi/3G/4G)或短信进行安全通信,所有TextSecure消息都可以在设备上本地加密,...
  • 下面是我的毕业设计,是一个Android短信查询系统,系统支持根据短信号码、短信内容、短信发生时间进行多条件的短信查询。支持检索条件的与运算和或运算。扩展了会话加密、转发/存短信、收/发短信等功能。需要强调...
  • 上回介绍了系统的会话加密功能的实现,这回介绍一下短信查询功能。软件实现了根据联系人号码、短信内容、短信发生时间进行多条查询,支持查询条件的或运算和与运算。多条件查询指的是多个查询字段的联合查询,可以...
  • 消息装甲 通过 Android 应用程序加密短信
  • 它本身并不是某一个聊天软件的外挂,而是安装安卓操作系统【无障碍辅助工具】。Oversec通过屏幕取词的方式,识别输入框提示用户是否需要加密,同时能自动识别加密文本提示解密口令。Oversec加密解密几乎任何应用中的...
  • 基于Android平台的短信安全评估与加密保护系统(APP客户端部分) —— 南京大学2018-2019大学生创新创业训练项目 (APP客户端部分) 安装包(APK文件) 下载地址 关于源代码的使用 Android客户端的部分功能需要与...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,246
精华内容 3,298
关键字:

安卓短信加密