好久没更新文章了,近期在做通讯录上传,把它分享出来,送给需要的朋友。
写了一个通讯录工具类,直接放代码吧,关键位置通过注释来解释。
这个工具类包含通讯录获取,加密,然后上传操作。看不懂的可以留言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | 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();//上报通讯录信息即可
上面解密后的数据日志为(声明:通讯录数据都是假数据,如有雷同,纯属巧合,可联系我删除):
原数据是上面这样,中间是有点的,下面这个被编辑器去掉了
1 2 | 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 |
获取通讯录需要权限,记着提前申请:
1 | Manifest.permission.READ_CONTACTS |
----------附上base64位加密后面附带的参数解释----
CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LF
DEFAULT 这个参数是默认,使用默认的方法来加密
NO_PADDING 这个参数是略去加密字符串最后的”=”
NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了)
URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/
----------------------------------------------