Android获取通讯录并上传(包含通讯录加密)
好久没更新文章了,近期在做通讯录上传,把它分享出来,送给需要的朋友。
写了一个通讯录工具类,直接放代码吧,关键位置通过注释来解释。
这个工具类包含通讯录获取,加密,然后上传操作。看不懂的可以留言
import android.database.Cursor;
import android.os.AsyncTask;
import android.provider.ContactsContract;
import android.util.Base64; import com.demo.alfar.app.AlfarApplication;
import com.demo.alfar.data.ActionDataManager;
import com.demo.alfar.data.common.BaseThrowable;
import com.demo.alfar.data.model.ConfigurationInfo;
import com.demo.alfar.data.model.EmptyData;
import com.demo.alfar.service.action.DeviceActionMvpView;
import com.demo.alfar.service.action.DeviceActionPresenter;
import com.demo.common.utils.LogUtil;
import com.demo.common.utils.SpFileUtil;
import com.demo.common.utils.StringUtils; import java.io.UnsupportedEncodingException;
import java.util.List; public class ContactReader { //通过下面字符进行分割,组成字符串
static String fieldSplit = "\u0001";
static String lineSplit = "\u0002"; static String newStr; public static class ContactReaderReporter extends AsyncTask<String, Void, Integer> {
@Override
protected Integer doInBackground(String... argus) {
String contactInfo = ""; Cursor cursor = null;
try {
cursor = AlfarApplication.getApplication().getContentResolver()
.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
int contactIdIndex = 0;
int nameIndex = 0; if (cursor.getCount() > 0) {
contactIdIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID);
nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
}
while (cursor.moveToNext()) {
String element = "";
String contactId = cursor.getString(contactIdIndex);
String name = cursor.getString(nameIndex);
element = name + fieldSplit;
Cursor phones = null;
try {
/*
* 查找该联系人的phone信息
*/
phones = AlfarApplication.getApplication().getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId, null, null);
int phoneIndex = 0;
if (phones.getCount() > 0) {
phoneIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
}
while (phones.moveToNext()) {
String phoneNumber = phones.getString(phoneIndex);
element += phoneNumber + lineSplit;
}
} catch (Exception e) {
} finally {
if (phones != null) {
phones.close();
}
}
Cursor emails = null;
try {
/*
* 查找该联系人的email信息
*/
emails = AlfarApplication.getApplication().getContentResolver()
.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=" + contactId, null, null);
int emailIndex = 0;
if (emails.getCount() > 0) {
emailIndex = emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
}
while (emails.moveToNext()) {
String email = emails.getString(emailIndex);
element += email + fieldSplit;
}
} catch (Exception e) {
// TODO: handle exception
} finally {
if (emails != null) {
emails.close();
}
}
element += lineSplit;
contactInfo += element; }
if (StringUtils.isNotEmpty(contactInfo)) {
LogUtil.Y("prePhoneNum:" + contactInfo);
newStr = encodeStr(contactInfo);
LogUtil.Y("finalPhoneNum:" + newStr);
//这个是mvp模块中的网络请求部分,可忽略一下逻辑,也可进行替换
DeviceActionPresenter actionDataManager = new DeviceActionPresenter(new ActionDataManager());
actionDataManager.attachView(new DeviceActionMvpView() {
@Override
public void onDeviceActionSuccess(EmptyData response) {
SpFileUtil.saveBoolean(AlfarApplication.getApplication(), SpFileUtil.FILE_PARAMS_DATA, SpFileUtil.KEY_POST_CONTENT_SUCCEED, true);
} @Override
public void onDeviceActionFail(BaseThrowable response) {
SpFileUtil.saveBoolean(AlfarApplication.getApplication(), SpFileUtil.FILE_PARAMS_DATA, SpFileUtil.KEY_POST_CONTENT_SUCCEED, false);
} @Override
public void onGetConfigurationsSuccess(List<ConfigurationInfo> response) { } @Override
public void showLoading() { } @Override
public void hideLoading() { }
});
actionDataManager.postClientContent(newStr);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (cursor != null) {
cursor.close();
cursor = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null; } } /**
* 执行上传操作
*/
static public void onContactURLReport() {
Boolean isSuccess = SpFileUtil.getBoolean(AlfarApplication.getApplication(), SpFileUtil.FILE_PARAMS_DATA, SpFileUtil.KEY_POST_CONTENT_SUCCEED, false);
if (!isSuccess) {
try {
ContactReaderReporter task = new ContactReaderReporter();
task.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 加密字符串,这是一个简单的算法,先base64加密之后,进行字符反转,服务端解密时候同样先进行字符反转,换成=号即可,然后再decode即可
*
* @param info
* @return
*/
public static String encodeStr(String info) { String baseStr = null;
try {
baseStr = Base64.encodeToString(info.getBytes("UTF-8"), Base64.NO_PADDING | Base64.NO_WRAP);
} catch (Exception e) {
e.printStackTrace();
}
String newStr = "";
int half = baseStr.length() / 2;
for (int i = 0; i < half; ++i) {
if (i % 2 != 0) {
newStr = newStr + (char) (baseStr.codePointAt(baseStr.length() - 1 - i));
} else {
newStr = newStr + (char) (baseStr.codePointAt(i));
}
}
if (baseStr.length() % 2 == 1) {
newStr = newStr + (char) (baseStr.codePointAt(baseStr.length() / 2));
}
for (int i = half - 1; i >= 0; --i) {
if (i % 2 != 0) {
newStr = newStr + (char) (baseStr.codePointAt(i));
} else {
newStr = newStr + (char) (baseStr.codePointAt(baseStr.length() - 1 - i));
}
}
return newStr; }
}
使用方法就是:
ContactReader.onContactURLReport();//上报通讯录信息即可
上面解密后的数据日志为(声明:通讯录数据都是假数据,如有雷同,纯属巧合,可联系我删除):

原数据是上面这样,中间是有点的,下面这个被编辑器去掉了
12-21 18:42:51.018 com.demo.alfar I/===y: prePhoneNum:马云18516886666骚扰电话15321114592广告推销17343150842李彦宏电话15301102735咋骗电话18101055214马化腾18666666666李科云18555555555
12-21 18:42:51.019 com.demo.alfar I/===y: finalPhoneNum:6gm15Tq1ATE1NTE4OTgRNLYRA6LOqprCigD2ljX2rj02MDUxMgEFMuQMOOIpAuWCvTWyiTawqDmxgTEBN5MoMLEnMpgpMoIl5g215z2y5T6x5zS16T+dAKE1M5APMaAmNbMOApLCkgv0qDf1lzX0rz0xMAgUMOEONuURM+Q5AumCrTW1lTixvjEzOTYBN5YoNLYnNbIm5p2p5ge25jq2ADE2NTU4NTURNLUsAaI
获取通讯录需要权限,记着提前申请:
Manifest.permission.READ_CONTACTS
----------附上base64位加密后面附带的参数解释----
CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LF
DEFAULT 这个参数是默认,使用默认的方法来加密
NO_PADDING 这个参数是略去加密字符串最后的”=”
NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了)
URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/
----------------------------------------------
Android获取通讯录并上传(包含通讯录加密)的更多相关文章
- 简单的 Android 拍照并显示以及获取路径后上传
简单的 Android 拍照并显示以及获取路径后上传 Activity 中的代码,我只贴出重要的事件部分代码 public void doPhoto(View view) { destoryBimap ...
- Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...
- android+nutz后台如何上传和下载图片
android+nutz后台如何上传和下载图片 发布于 588天前 作者 yummy222 428 次浏览 复制 上一个帖子 下一个帖子 标签: 无 最近在做一个基于android的ap ...
- Android连接socket服务器上传下载多个文件
android连接socket服务器上传下载多个文件1.socket服务端SocketServer.java public class SocketServer { ;// 端口号,必须与客户端一致 ...
- Android+Spring Boot 选择+上传+下载文件
2021.02.03更新 1 概述 前端Android,上传与下载文件,使用OkHttp处理请求,后端使用Spring Boot,处理Android发送来的上传与下载请求.这个其实不难,就是特别多奇奇 ...
- Android端通过HttpURLConnection上传文件到服务器
Android端通过HttpURLConnection上传文件到服务器 一:实现原理 最近在做Android客户端的应用开发,涉及到要把图片上传到后台服务器中,自己选择了做Spring3 MVC HT ...
- Springboot框架中request.getInputStream()获取不到上传的文件流
Springboot框架中用下面的代码,使用request.getInputStream()获取不到上传的文件流 @PostMapping("/upload_img") publi ...
- Android端通过HttpURLConnection上传文件到server
Android端通过HttpURLConnection上传文件到server 一:实现原理 近期在做Androidclient的应用开发,涉及到要把图片上传到后台server中.自己选择了做Sprin ...
- Android实现TCP断点上传,后台C#服务实现接收
终端实现大文件上传一直都是比较难的技术,其中涉及到后端与前端的交互,稳定性和流量大小,而且实现原理每个人都有自己的想法,后端主流用的比较多的是Http来实现,因为大多实现过断点下载.但稳定性不能保证, ...
随机推荐
- Qt错误 —— 无法启动此程序 因为计算机丢失QtCore5.dll 以及 无法定位程序输入点于动态链接库QtCore5.dll
首先,设置计算机的环境变量Path,计算机=>右键属性=>高级设置=>环境变量=>系统变量=>双击Path,在Path后面增加C:\Qt\Qt5.8.0\5.8\ming ...
- TMS320DM642开发之Bug1-Memory map error:READ access by cpu to address 0x1b3f018(Device Config Space)which is not supported in simulator
load程序到DM642开发板上之后,点击了run按钮出现了如下的错误: Memory map error:READ access by cpu to address 0x1b3f018(Device ...
- html-字体属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- CodeForces 433C Ryouko's Memory Note (中位数定理)
<题目链接> 题目大意:给你一堆数字,允许你修改所有相同的数字成为别的数字,不过只能修改一次,问你修改后序列相邻数字的距离和最小是多少. 解题分析: 首先,修改不是任意的,否则那样情况太多 ...
- HDU 4463 Outlets 【最小生成树】
<题目链接> 题目大意: 给你一些点的坐标,要求你将这些点全部连起来,但是必须要包含某一条特殊的边,问你连起这些点的总最短距离是多少. 解题分析: 因为一定要包含那条边,我们就记录下那条边 ...
- Linux添加系统环境变量
在Linux下使用源码安装软件的时候,通常只能在软件安装目录下使用该软件命令(使用yum命令安装的除外),这样太麻烦,我们希望全局使用,可以将软件安装路径添加到系统环境变量里. 添加环境变量有2种方法 ...
- 实现简单的web框架
实现简单的web框架 流程: 服务端启动---服务端等待请求---客户端访问---服务端响应请求 代码: from wsgiref.simple_server import make_server # ...
- UVA 2519 Radar Installtion
思路: #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> ...
- 机器学习系列-tensorflow-01-急切执行API
tensorflow急切执行概述 Eager execution is an imperative, define-by-run interface where operations are exec ...
- Linux服务部署--Java(一)
网络配置 一.配置dns 1.修改/etc/NetworkManager/NetworkManager.conf 文件,在main部分添加 “dns=none” 选项: 2.NetworkManage ...