现在很多人打电话都会使用一个套餐,比较划算。通常一个月有多少分钟免费呼叫,几十到几百条的免费短信。我自己写了一个小软件,可以统计一个月打出的电话总时间,可以帮助使用套餐的同学们把握好免费呼叫的时间。

   一般来讲,android会将通话记录都保存在一个特定的contentprovider中,用手机查看的通话记录也是从里面查询出来的数据。操作这个contentprovider的类就是CallLog类,它有一个内部类Calls,在Calls中对uri等成员都已经做好了定义,可以使用Calls的成员直接进行通话记录的查询。当然,对通话记录的插入也是通过这个类来实现的。


   另外值得一提的是,如果在手机的通话记录中将所有的通话记录都删除了话,是查不出任何数据的。



   程序的界面我采用了AlertDialog的形式,本来实现的功能和要显示的内容就很简单,使用Activity的话感觉有点大。整个程序只有一个类TelTime.java,其实说起来很简单,就是读取出所有的通话记录,然后一条一条地按时间进行分类求和而已。

1. package org.test;
2.  
3. import .Activity;
4. import .AlertDialog;
5. import android.content.ContentResolver;
6. import android.content.DialogInterface;
7. import android.database.Cursor;
8. import android.os.Bundle;
9. import android.provider.CallLog;
10. import android.util.Log;
11. import android.view.View;
12. import android.widget.TextView;
13.  
14. import java.text.SimpleDateFormat;
15. import java.util.Date;
16. import java.util.HashMap;
17. import java.util.Map;
18. import java.util.Set;
19.  
20. public class TelTime extends Activity implements DialogInterface.OnCancelListener {
21. private TextView outView;
22.  
23. private TextView inView;
24.  
25. private TextView out;
26.  
27. private TextView in;
28.  
29. View view;
30.  
31. int type;
32.  
33. long callTime;
34.  
35. long totalOutTime = 0;
36.  
37. int totalOutCall = 0;
38.  
39. long totalInTime = 0;
40.  
41. int totalInCall = 0;
42.  
43. long singleTime = 0;
44.  
45. dialog;
46.  
47. Date date;
48.  
49. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
50.  
51. String nowTime;
52.  
53. String tagTime = "";
54.  
55. String time;
56.  
57. String name;
58.  
59. Map<String, MonthTime> monthMap = new HashMap<String, MonthTime>();
60.  
61. Map<String, Integer> mInMap = new HashMap<String, Integer>();
62.  
63. Map<String, Integer> mOutMap = new HashMap<String, Integer>();
64.  
65. ;
66.  
67. public void onCreate(Bundle savedInstanceState) {
68. super.onCreate(savedInstanceState);
69. // requestWindowFeature(Window.FEATURE_NO_TITLE);
70. = format.format((new Date()));
71. = getContentResolver();
72. final Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, new String[] {
73. .Calls.TYPE, CallLog.Calls.DATE, CallLog.Calls.DURATION,
74. .Calls.CACHED_NAME
75. }, null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
76. for (int i = 0; i < cursor.getCount(); i++) {
77. cursor.moveToPosition(i);
78. type = cursor.getInt(0);
79. = cursor.getLong(2);
80. name = cursor.getString(3);
81. date = new Date(Long.parseLong(cursor.getString(1)));
82. time = format.format(date);
83. if (!time.equals(tagTime)) {
84. if (tagTime.equals("")) {
85.  
86. } else {
87. .mostInPeople = getMost(mInMap);
88. .mostInTimes = mInMap.get(currentMonth.mostInPeople);
89. .mostOutPeople = getMost(mOutMap);
90. .mostOutTimes = mOutMap.get(currentMonth.mostOutPeople);
91. .put(tagTime, currentMonth);
92. .clear();
93. .clear();
94. }
95. = new MonthTime();
96. = time;
97. // if (monthMap.containsKey(time)) {
98. // currentMonth = monthMap.get(time);
99. // monthMap.remove(time);
100. // } else {
101. // currentMonth = new MonthTime();
102. // }
103. }
104. if (callTime % 60 != 0) {
105. = callTime / 60 + 1;
106. } else {
107. = callTime / 60;
108. }
109. if (type == 1) {
110. .totalInCall++;
111. .totalInTime = currentMonth.totalInTime + singleTime;
112. if (mInMap.containsKey(name)) {
113. Integer time = mInMap.get(name);
114. .remove(name);
115. .put(name, time + 1);
116. } else {
117. if (name != null) {
118. .put(name, 1);
119. }
120. }
121. }
122. if (type == 2) {
123. .totalOutCall++;
124. .totalOutTime = currentMonth.totalOutTime + singleTime;
125. if (mOutMap.containsKey(name)) {
126. Integer time = mOutMap.get(name);
127. .remove(name);
128. .put(name, time + 1);
129. } else {
130. if (name != null) {
131. .put(name, 1);
132. }
133. }
134. // Log.d("test", "name:" + name);
135. // Log.d("test", "time :" + tagTime);
136. }
137. if (type == 3) {
138. if (mInMap.containsKey(name)) {
139. Integer time = mInMap.get(name);
140. .remove(name);
141. .put(name, time + 1);
142. } else {
143. if (name != null) {
144. .put(name, 1);
145. }
146. }
147. }
148.  
149.  
150. }
151.  
152. showDialog(nowTime);
153. }
154.  
155. public void onStart() {
156. super.onStart();
157.  
158. }
159.  
160. private void showDialog(final String time) {
161. view = getLayoutInflater().inflate(R.layout.main, null);
162.  
163. = (TextView)view.findViewById(.outtime);
164. = (TextView)view.findViewById(.intime);
165. = (TextView)view.findViewById(.out);
166. in = (TextView)view.findViewById(.in);
167. if (monthMap.containsKey(time)) {
168. .setText("本月共接听电话:" + monthMap.get(time).totalInCall + "次\n总接听时间:"
169. + monthMap.get(time).totalInTime + "分钟");
170. .setText("本月共拨打电话:" + monthMap.get(time).totalOutCall + "次\n总拨打时间:"
171. + monthMap.get(time).totalOutTime + "分钟");
172. in.setText("本月最关心你的是:" + monthMap.get(time).mostInPeople + "\n共给你打过"
173. + monthMap.get(time).mostInTimes + "次电话");
174. .setText("本月你最关心的是:" + monthMap.get(time).mostOutPeople + "\n你共给他(她)打过"
175. + monthMap.get(time).mostOutTimes + "次电话");
176. dialog = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info)
177. .setTitle(time + " 通话时间统计").setView(view)
178. .setPositiveButton("上个月", new DialogInterface.OnClickListener() {
179. public void onClick(DialogInterface dialog, int which) {
180. (time, 0);
181.  
182. }
183. }).setNegativeButton("下个月", new DialogInterface.OnClickListener() {
184. public void onClick(DialogInterface dialog, int which) {
185. (time, 1);
186. }
187. }).create();
188. dialog.setOnCancelListener(this);
189. dialog.show();
190. } else {
191. .setText("本月共接听电话:" + 0 + "次\n总接听时间:" + 0 + "分钟");
192. .setText("本月共拨打电话:" + 0 + "次\n总拨打时间:" + 0 + "分钟");
193. dialog = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info)
194. .setTitle(time + "通话时间统计").setView(view)
195. .setPositiveButton("上个月", new DialogInterface.OnClickListener() {
196. public void onClick(DialogInterface dialog, int which) {
197. (time, 0);
198. }
199. }).setNegativeButton("下个月", new DialogInterface.OnClickListener() {
200. public void onClick(DialogInterface dialog, int which) {
201. (time, 1);
202. }
203. }).create();
204. dialog.setOnCancelListener(this);
205. dialog.show();
206. }
207. }
208.  
209. private String getMost(Map<String, Integer> map) {
210. String mostName = "";
211. Set<String> totalName = map.keySet();
212. Integer most = 0, current=0;
213. for (String name : totalName) {
214. current = map.get(name);
215. if (current > most) {
216. = current;
217. = name;
218.  
219. }
220. }
221. return mostName;
222. }
223.  
224. class MonthTime {
225. long totalOutTime = 0;
226.  
227. int totalOutCall = 0;
228.  
229. long totalInTime = 0;
230.  
231. int totalInCall = 0;
232.  
233. String mostInPeople = "";
234.  
235. String mostOutPeople = "";
236.  
237. Integer mostInTimes = 0;
238.  
239. Integer mostOutTimes = 0;
240. }
241.  
242. private void updateView(String time, int mode) {
243. String year = time.substring(0, 4);
244. String month = time.substring(5, 7);
245. int iMonth = 0;
246. if (mode == 0) {
247. if (month.equals("01")) {
248. = String.valueOf(Integer.parseInt(year) - 1);
249. = "12";
250.  
251. } else {
252. = Integer.parseInt(month) - 1;
253. if (iMonth < 10) {
254. = "0" + iMonth;
255. } else {
256. = String.valueOf(iMonth);
257. }
258. }
259. } else {
260. if (month.equals("12")) {
261. = String.valueOf(Integer.parseInt(year) + 1);
262. = "01";
263.  
264. } else {
265. = Integer.parseInt(month) + 1;
266. if (iMonth < 10) {
267. = "0" + iMonth;
268. } else {
269. = String.valueOf(iMonth);
270. }
271. }
272. }
273. showDialog(year + "-" + month);
274. Log.d("test", month);
275. Log.d("test", year);
276. }
277.  
278. Override
279. public void onCancel(DialogInterface dialog) {
280. finish();
281.  
282. }
283.  
284. }


    要只显示一个Dialog,需要把背景的Activity设置为透明的就可以了,这个在manifest文件中进行设置:

1. <?xml version="1.0" encoding="utf-8"?>
2. <manifest xmlns:android="http:///apk/res/android"
3. ="org.test"
4. ="1"
5. ="1.0">
6. <uses-permission android:name="android.permission.READ_CONTACTS" />
7.  
8. <application android:icon="@drawable/icon" android:label="@string/app_name">
9.  
10. <activity android:name=".TelTime"
11. ="@string/app_name"
12. ="@android:style/Theme.Translucent">
13. <intent-filter>
14. <action android:name="android.intent.action.MAIN" />
15. <category android:name="android.intent.category.LAUNCHER" />
16. </intent-filter>
17. </activity>
18.  
19. </application>
20. </manifest>
 
 

       对于Dialog的布局也很简单,只是采用了四个TextView。 
 
 
 
 
  
 
 
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout
3. ="http:///apk/res/android"
4. ="vertical"
5. ="fill_parent"
6. ="fill_parent">
7. <TableLayout
8. ="wrap_content"
9. ="wrap_content"
10. ="1"
11. ="5dip">
12. <TableRow>
13. <TextView
14. ="@+id/outtime"
15. ="wrap_content"
16. ="wrap_content"
17. ="20dip"
18. ="#fff00000" />
19. </TableRow>
20. <TableRow>
21. <TextView
22. ="@+id/intime"
23. ="wrap_content"
24. ="wrap_content" 
25. ="20dip" 
26. ="#ff00ffff"/>
27. </TableRow>
28. <TableRow>
29. <TextView
30. ="@+id/out"
31. ="wrap_content"
32. ="wrap_content"
33. ="20dip"
34. ="#fff0ff00" />
35. </TableRow>
36. <TableRow>
37. <TextView
38. ="@+id/in"
39. ="wrap_content"
40. ="wrap_content" 
41. ="20dip" 
42. ="#ff00ff00"/>
43. </TableRow>
44. </TableLayout>
45. </LinearLayout>


    最后,附上一个示例图片,如果有通话记录还会显示出你最关心的人和最关心你的人。





即时通话 android 安卓通话app_通话记录