转载请注明出处:周木水的CSDN博客 http://blog.csdn.net/zhoumushui
最近部门没什么大的需求要改,就让我们改一下Android 4.4的拨号器,联系人以及短信源码。以微信电话本为蓝本,进行布局定制和功能完善。我主要负责拨号模块,涉及拨号面板,通话记录和通话详情这几个修改点。到今天差不多已经完成,下面总结一下过程中遇到的一些问题以及解决步骤:
相应模块实现功能:
①通话记录:运营商显示,ListView条目向右滑动拨号、向左滑动发短信,相同联系人记录合并,
②通话详情:号码归属地显示,联系人标星收藏,加入黑名单来电拦截,显示联系人头像,发送名片,通话记录显示最近5条,超过5条显示More按钮,点击可查看全部记录
======================================================================================================
1.将服务器目录挂载到本地:
- sshfs zhoumushui@168.168.0.55:../zhoumushui localcode/
2.源码布局分析
res/layout/diapad.xml
包括数字1-9,0,*,#以及对应英文字母。
res/layout/diapad_key.xml
数字0-9的,*,#,字母的属性,大小和颜色
res/layout/dialpad_fragment.xml
包括拨号面板的号码输入框,退格。下面链接dialpad.xml。下面是通话记录,拨号键,overflow menu
res/layout/dialtacts_activity.xml
打开拨号的默认界面,未呼出dialpad
res/layout/phone_no_favorites.xml
文字提示“您收藏的联系人和经常通话的……”,“所有联系人”按钮
res/layout/call_log_fragment.xml
通话记录的过滤查看(全部,来电,去电,未接)按钮
res/layout/call_log_list_item.xml
(拨号首页)通话记录具体条目内容:头像QuickPhoto,名字Name,标签Label,通话类型call_type,通话时长和日期call_count_and_date,secondary_action_icon,
res/layout/call_detail.xml
通话详情界面,包括main_action_push_layer,header_text,main_action,call_and_sms_action等。
res/layout/mtk_dialer_search_item_view.xml
拨号界面输入号码后,页面上端匹配联系人条目的布局文件,包括qucik_contact_photo, name, labelAndNumber等。
res/menu/call_log_options.xml
通话记录列表actionBar上的操作按钮:选择资源,删除。
com/android/dialer/PhoneCallDetailsView.java
显示通话记录条目的具体内容:包括name,callTyepe,callTypeIcons,call_count_and_date,label
3.编译命令
整体编译:
- ./mk -t -l=*** -o=TARGET_BUILD_VARIANT=*** n
-t表示打印出编译log信息
模块编译:
- ./mk -t mm packages/apps/Dialer
输出文件夹:
- out/target/product/***/system/priv-app/Dialer.apk
4.adb的一些操作
- adb push xxxx.apk /system/app 将应用程序的apk文件push到手机中
- adb install xxxx.apk 安装app
- adb install -r ~/Dialer.apk
5.".9.png"图片原理和制作
左侧和上方的黑线交叉的部分即可扩展区域
右侧和下方的黑线交叉的部分即内容显示区域(如做button背景图时,button上文字的显示区域)
6.让Android4.0以上机器的虚拟按键中显示menu键
在Activity的onCreate中设置flag:
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY,WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
7.Visibility的三种属性
1) 可见(visible)
XML文件:android:visibility="visible"
Java代码:view.setVisibility(View.VISIBLE);
2) 不可见(invisible)
XML文件:android:visibility="invisible"
Java代码:view.setVisibility(View.INVISIBLE);
3) 隐藏(GONE)
XML文件:android:visibility="gone"
Java代码:view.setVisibility(View.GONE);
8.去掉ListView的分割线
去掉分割线,把divider的颜色设为透明就行:android:divider="#00000000"
点击之后不让被点击项变成橘黄色:android:listSelector="#00000000"
9.setClickable,setFocusable
setClickable()控制按钮是否可以被点击和点击之后触发监听器事件。
setFocusable()控制键盘是否可以获得这个按钮的焦点。
10.寻找文件中关键字
- find -name "*.java" | xargs grep -n "ic_phone_dk"
- find -name "*.xml" | xargs grep -n "ic-phone_dk"
11.去掉Activity间的跳转动画
①在values文件夹的styles.xml文件里面新建一个style
- <style name="AlexNoAniTheme" parent="android:Theme">
- <item name="android:windowAnimationStyle">@style/noAnimation</item>
- <item name="android:windowNoTitle">true</item></style>
- <style name="noAnimation">
- <item name="android:activityOpenEnterAnimation">@null</item>
- <item name="android:activityOpenExitAnimation">@null</item>
- <item name="android:activityCloseEnterAnimation">@null</item>
- <item name="android:activityCloseExitAnimation">@null</item>
- <item name="android:taskOpenEnterAnimation">@null</item>
- <item name="android:taskOpenExitAnimation">@null</item>
- <item name="android:taskCloseEnterAnimation">@null</item>
- <item name="android:taskCloseExitAnimation">@null</item>
- <item name="android:taskToFrontEnterAnimation">@null</item>
- <item name="android:taskToFrontExitAnimation">@null</item>
- <item name="android:taskToBackEnterAnimation">@null</item>
- <item name="android:taskToBackExitAnimation">@null</item></style>
②在AndroidManifest.xml中修改相应Activity的theme
- <activity android:name=".HomeActivity"
- android:label="@string/app_name"
- android:theme="@style/AlexNoAniTheme">
或者将 <item name="android:windowAnimationStyle">@style/noAnimation</item>加入Activity原来的theme
源码修改过程中遇到不少或大或小的问题,接着昨天总结吧。
12.设置分割线
横线:
- <View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="?android:attr/listDivider"
- />
竖线:
- <View
- android:layout_width="1px"
- android:layout_height="fill_parent"
- android:background="?android:attr/listDivider" />
13.调用系统发短信界面
- Uri uri = Uri.parse("smsto:" + callLog.getNumber());
- Intent it = new Intent(Intent.ACTION_SENDTO, uri);
-
- ctx.startActivity(it);
14.adb查看真机log
- adb logcat *:E // Error级别,其他可类比
15.锁定Activity的屏幕方向
在Manifest文件中对应Activity属性中添加: //在application中添加是不是整个应用都有效?不是
- android:screenOrientation="nosensor"
16.Toast常犯错误
Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); // 常犯错误:忘了调用 show 方法,调试的时候死活不见吐司,搞的晕头转向,生生没有看见ADT的高亮显示,结果是这么明显的错误
17. LinearLayout
也可以有onClick属性,也可以findById,哈哈。这个很好用啊。
18.ActionBar返回上一层
- import android.app.ActionBar;
Activity onCreate()中:
- ActionBar actionBar = getActionBar();
- actionBar.setHomeButtonEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
在
public boolean onOptionsItemSelected(MenuItem item) 中添加一个case:
- case android.R.id.home:
- finish();
- break;
19.在Adapter中进行跳转Activity
不同于Activity,Adapter中的跳转用上Context就可以了。
- <p><span style="font-size: 14px;"></span></p>
- private Context ctx;
- 对应跳转代码:
- Intent intent = new Intent(ctx,
- com.android.dialer.calllog.RecordDetail.class);
- intent.putExtra("mNum", callLog.getNumber());
- ctx.startActivity(intent);
-
-
- int version = Integer.valueOf(android.os.Build.VERSION.SDK);
- if (version > 5) {
- ((Activity)ctx).overridePendingTransition(
- com.android.dialer.R.anim.push_left_in,
- com.android.dialer.R.anim.push_left_out);
- }
-
20.overflow menu内容显示图标
其实,overflow中的Action按钮应不应该显示图标,是由MenuBuilder这个类的setOptionalIconsVisible变量来决定的,如果我们在overflow被展开的时候将这个变量赋值为true,那么里面的每一个Action按钮对应的图标就都会显示出来了。赋值的方法仍然是用反射了,代码如下:
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
- if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
- try {
- Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
- m.setAccessible(true);
- m.invoke(menu, true);
- } catch (Exception e) {
- }
- }
- }
- return super.onMenuOpened(featureId, menu);
- }
21.View的setVisibiility()
android view setVisibility():
有三个参数:Parameters:visibility One of VISIBLE, INVISIBLE, or GONE,想对应的三个常量值:0、4、8
VISIBLE:0 意思是可见的
INVISIBILITY:4 意思是不可见的,但还占着原来的空间
GONE:8 意思是不可见的,不占用原来的布局空间
22.联系人接口
添加号码到联系人或新建联系人:
- Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.setType("vnd.android.cursor.item/contact");
- intent.putExtra(Intents.Insert.PHONE, number);
- startActivity(intent);
直接添加联系人:
- Intent intent = new Intent(Contacts.Intents.Insert.ACTION);
- intent.setType(Contacts.People.CONTENT_TYPE);
- intent.putExtra(Contacts.Intents.Insert.NAME, "zhangsan");
- intent.putExtra(Contacts.Intents.Insert.PHONE, number);
- intent.putExtra(Contacts.Intents.Insert.PHONE_TYPE,Contacts.PhonesColumns.TYPE_MOBILE);
- intent.putExtra(Contacts.Intents.Insert.EMAIL, "");
- intent.putExtra(Contacts.Intents.Insert.COMPANY,"http://orgcent.com");
- startActivity(intent);
=====
根据number获取ContactId,然后编辑指定联系人:
- String str = getContactId(this, number);
- long contactId = Long.parseLong(str);
-
- Intent intent = new Intent(Intent.ACTION_EDIT);
- intent.setData(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,contactId));
- startActivity(intent);
-
- public static String getContactId(Context context, String number) {
- Cursor c = null;
- try {
- c = context.getContentResolver().query(Phone.CONTENT_URI,
- new String[] { Phone.CONTACT_ID, Phone.NUMBER }, null,
- null, null);
- if (c != null && c.moveToFirst()) {
- while (!c.isAfterLast()) {
- if (PhoneNumberUtils.compare(number, c.getString(1))) {
- return c.getString(0);
- }
- c.moveToNext();
- }
- }
- } catch (Exception e) {
-
- } finally {
- if (c != null) {
- c.close();
- }
- }
- return null;
- }
今天就到这儿吧,明天继续。
晚上出去逛了一下,刚刚回来,虽然时间有点晚了,还是得继续啊,嘿嘿~
23.根据number获取联系人名字(若存在)
-
- public String getContactNameByPhoneNumber(String number) {
- if (TextUtils.isEmpty(number)) {
- return null;
- }
- final ContentResolver resolver = ctx.getContentResolver();
- Uri lookupUri = null;
- String[] projection = new String[] { PhoneLookup._ID,
- PhoneLookup.DISPLAY_NAME };
- Cursor cursor = null;
- try {
- lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
- Uri.encode(number));
- cursor = resolver.query(lookupUri, projection, null, null, null);
- } catch (Exception ex) {
- ex.printStackTrace();
- try {
- lookupUri = Uri.withAppendedPath(
- android.provider.Contacts.Phones.CONTENT_FILTER_URL,
- Uri.encode(number));
- cursor = resolver
- .query(lookupUri, projection, null, null, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- String name = null;
- if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
- name = cursor
- .getString(cursor
- .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
- }
- cursor.close();
- return name;
- }
24.根据ContactId获取联系人头像
-
- public byte[] getPhoto(String people_id) {
- String photo_id = null;
- String selection1 = ContactsContract.Contacts._ID + " = " + people_id;
- Cursor cur1 = getContentResolver().query(
- ContactsContract.Contacts.CONTENT_URI, null, selection1, null,
- null);
- if (cur1.getCount() > 0) {
- cur1.moveToFirst();
- photo_id = cur1.getString(cur1
- .getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
-
- }
- String selection = null;
- if (photo_id == null) {
- return null;
- } else {
- selection = ContactsContract.Data._ID + " = " + photo_id;
- }
- String[] projection = new String[] { ContactsContract.Data.DATA15 };
- Cursor cur = getContentResolver().query(
- ContactsContract.Data.CONTENT_URI, projection, selection, null,
- null);
- cur.moveToFirst();
- byte[] contactIcon = cur.getBlob(0);
-
- if (contactIcon == null) {
- return null;
- } else {
- return contactIcon;
- }
- }
-
-
- public void setPhoto(String contactId) {
-
- ImageButton ibAvatar = (ImageButton) this
- .findViewById(com.android.dialer.R.id.zj_detail_avatar);
-
- byte[] photo = getPhoto(contactId);
- if (photo != null) {
- Bitmap map = BitmapFactory.decodeByteArray(photo, 0, photo.length);
- ibAvatar.setImageBitmap(map);}
- }
-
25.Monkey调试
指定应用程序,并向其发送1000个伪随机事件:
- adb shell monkey -p com.android.dialer -v 1000
Monkey测试的停止条件
Monkey Test执行过程中在下列三种情况下会自动停止:
(1)如果限定了Monkey运行在一个或几个特定的包上,那么它会监测试图转到其它包的操作,并对其进行阻止。
(2)如果应用程序崩溃或接收到任何失控异常,Monkey将停止并报错。
(3)如果应用程序产生了应用程序不响应(application not responding)的错误,Monkey将会停止并报错。
通过多次并且不同设定下的Monkey测试才算它是一个稳定性足够的程序。
26.DDMS里面的Dump View Hierarchy for UI Automator
修改源码很痛苦的一件事就是分析每个界面的布局文件和代码文件分别是哪些。动则十几个package,分析起来很是头疼,这个工具可以小小的帮助我们一下。当然也可以用find命令查找资源在xml中的位置,然后在根据xml布局文件的名字在java中查找。以下是在网上找到的描述:
用来分析应用当前界面的View层次节点的,假设你现在是在用模拟器手机做调试,你用这个他就会构建一个你先在手机或模拟器显示界面的View的层次图,可以做一些性能的调优之类的。
27.putExtra获取到R.string中内容
- it.putExtra("sms_body", this.getString(com.android.dialer.R.string.zj_name) + ":" + name + "\n" + this.getString(com.android.dialer.R.string.zj_number) + ":"
- + number);
28.通话记录去除重复记录,即同一个联系人只显示一条
去除相同数据
- Uri uri = android.provider.CallLog.Calls.CONTENT_URI;
- String[] projection = { CallLog.Calls.DATE, CallLog.Calls.NUMBER,
- CallLog.Calls.TYPE, CallLog.Calls.CACHED_NAME,
- CallLog.Calls._ID, CallLog.Calls.DURATION, };
- asyncQuery.startQuery(0, null, uri, projection, "_id in (select max(_id)from calls group by number)", null,
- CallLog.Calls.DEFAULT_SORT_ORDER);
29.打开短信列表
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setType("vnd.android-dir/mms-sms");
- startActivity(intent);
30.短信数据库位置
文件 /data/data/com.android.providers.telephony/databases/mmssms.db
这个数据库有13张表,sms表存了短信信息。
推荐一个查看真机里面数据库文件的方法,RE文件浏览器,很赞哦,不过要Root机子。
31.打开拨号界面
- Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse("tel:13850734494"));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
32.启动另外一个应用的Activity
- ComponentName componetName = new ComponentName(
-
- "com.android.dialer",
-
- "com.android.dialer.calllog.Record");
- try {
- Intent intent = new Intent();
- intent.setComponent(componetName);
- startActivity(intent);
- } catch (Exception e) {
- }
33.使用ComponentName启动另一个应用的Activity时出现java.lang.SecurityException: Permission Denial的解决方案:
原因分析:
在SDK版本eclair中(Level 5-7?),如果activity没有设定intent-filter则无法被外部程序启动!
解决办法:
给对应的activity添加intent-filter字段,且必须带上action,即使为空也行:
- <intent-filter>
- <action android:name=""/>
- </intent-filter>
总结到这里的时候,由于另外两个同事有其他的事情要忙,我接手了联系人模块和短信模块,做后续的修改。
时间不早了,今天就到这吧。
有不明白的地方,欢迎交流。
接手了同事的短信模块和联系人模块,他们完成了基础功能,我做后续修改和功能强化。
短信模块主要增加了了以下功能:
短信会话加密(九宫格手势密码和字符密保),短信收藏。
联系人模块,实现了以下功能:
联系人列表长按多选群发短信,联系人右侧快速字母定位联系人,并且把标星联系人(☆)显示在列表前,非字母开头(#)显示在列表后。
联系人模块有较多的Bug,解决这些问题的过程也学到了不少。
话不多说,继续总结……
34.Cursor先获得制定列的下标,然后根据下标获得数据(不同系统的mmssms.db/sms标的列可能不同,i9250的原生4.3系统有17列,下标0-16.MTK的4.4.2有23列,下标0-22,多出几个自定义列)
- 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);
- ZjLockMsg newMsg = new ZjLockMsg(threadId,address,date,type,body);
35.DATABASE_VERSION的问题
注意DATABASE_VERSION 值的问题,在程序运行时,如果改变了表的个数,再次运行时会出错.这是因为数据库改变时,会调用DatabaseHelper类.执行
- super(context, DATABASE_NAME,null, DATABASE_VERSION )
这个方法,此时DATABASE_VERSION所对应的表的个数或者内容都是改变之前的, 这就造成异常的出现
36.使用Cursor使,读取里面的数据用到getColumnIndex()时报错:Index -1 requested, with a size of 1
仔细阅读过Cursor的文档,发现关于getColumnIndex()这个方法的说明如下:
public abstract int getColumnIndex (String columnName)
Since: API Level 1
Returns the zero-based index for the given column name, or -1 if the column doesn't exist. If you expect the column to exist use getColumnIndexOrThrow(String) instead, which will make the error more clear.
文档里清楚的表明:在要读取的列不存在的时候该方法会返回值“-1”。所以可知,以上报错可能是因为要get的列不存在,也可能是因为游标位置不对。后来发现,因为我在执行这个语句前没有执行“Cursor.moveToNext();”这个函数,导致游标还位于第一位置的前面,所以索引显示为“-1”,前面加上这句就没错了。
网上另有一种情况是用完Cursor没有关闭导致报此错误,所以也提醒各位用完Cursor要记得执行Cursor.close();
37.Your content must have a ListView whose id attribute is 'android.R.id.list'错误的解决办法
- <ListView
- android:id="@android:id/list" 或android:id="@id/android:list"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </ListView>
38.模糊查找历史命令
- history | grep -n "adb pull"
39.adb pull取设备中的数据库
- adb pull /data/data/com.android.mms/databases/zj_msg ~/
- adb pull /data/data/com.android.providers.telephony/databases/mmssms.db
40.多个设备时adb操作
在adb的指令后面加上参数 -s <serialNumber> 比如 -s emulator-5554
就可以指定adb指令的目标。
在多个模拟器或者设备存在时很实用。
- alex@alex-pc:~$ adb devices
- List of devices attached
- 0123456789ABCDEF device
- 016B7EB20100B003 device
- alex@alex-pc:~$ adb -s 0123456789ABCDEF install -r mtk/zj/8382/out/target/product/esky82_tb_cn_kk/system/priv-app/Mms.apk
41.setBackgroundDrawable和setBackgroundColor的用法
设置背景图片,图片来源于drawable;
- flightInfoPanel.setBackgroundDrawable(getResources().getDrawable(R.drawable.search_label_click));
转换字符串为int(颜色);
- listItemView.deleteFilghtBg.setBackgroundColor(Color.parseColor("#F5F5DC"));
42.联系人标星收藏,即更改数据库starred字段值为1
- ContentValues values = new ContentValues();
- values.put("starred", 1);
- this.getContentResolver().update(
- ContactsContract.RawContacts.CONTENT_URI, values,
- "contact_id = ?", new String[] { contactIdStr });
43.布局元素越界时,页面滚动
在LinearLayout外面包一层ScrollView即可,如下代码
ApiDemo 中关于如何使用ScrollView说明,请参考:
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:scrollbars="none">
- </ScrollView>
44.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
这样的问题主要是签名冲突造成的,比如你使用了ADB的debug权限签名,但后来使用标准sign签名后再安装同一个文件会出现这样的错误提示,解决的方法除了只有先老老实实从手机上卸载原有版本再进行安装,而adb install -r参数也无法解决这个问题。
45.cp命令移动隐藏文件
-a参数 所有文件,包括隐藏文件
-r参数 移动目录
所以备份时,直接cp -a -r 一步到位,省得一些点文件漏操作。
46.去除应用图标
去掉Manifest中Activity的对应标签:
- <category android:name="android.intent.category.LAUNCHER" />
47.修改framework内容后编译推入设备
- ./mk -t mm frameworks/base/
- adb push ***/out/target/product/***/system/framework/framework.jar /system/framework
- adb push ***/out/target/product/***/system/framework/framework2.jar /system/framework
48.根据RawContactId获取contacts表中的lookup字段
- public String getLookupKey(long contactId) {
-
-
-
- String lookupkey = "";
-
-
-
- Cursor cursor = getContentResolver().query(Contacts.CONTENT_URI, null,
- "name_raw_contact_id = ?", new String[] { "" + contactId },
- null);
- if (cursor.moveToFirst()) {
- do {
- int starIndex = cursor.getColumnIndex(Contacts.LOOKUP_KEY);
- Log.e("LookupKey Index:", "" + starIndex);
- lookupkey = cursor.getString(starIndex);
-
- } while (cursor.moveToNext());
-
- }
- cursor.close();
- return lookupkey;
- }
这些内容多是我工作时,总结到Evernote的,可能不够详细,有什么不明白的欢迎交流。
今天就到这儿了,去洗个澡,明天又是新的一周,加油~
台风要来了,滴了些雨,顿时凉爽了很多。源码修改,继续。
有些Bug让人摸不着头脑,等发现了触发条件,就大致有了个分析方向,最后自然也可以找到原因。程序就是这么实在,什么反馈都是有原因的,真好。
49.解决ListView条目在应用初次启动时只能点击一次的情况,注释addFlags代码:
- final Intent intent = new Intent(mPeopleActivity.this,
- ViewContactActivity.class);
- intent.setData(uri);
-
- startActivity(intent);
50.在Adapter的onTouch监听中设置View的Down和Up事件:
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- view.setBackgroundColor(Color.parseColor("#EBEBEB"));
- return false;
- } else if (event.getAction() == MotionEvent.ACTION_UP) {
- view.setBackgroundColor(Color.parseColor("#ffffff"));
- }
51.调整Bitmap对象的大小:
- public void setPhoto(String contactId) {
-
- ImageButton ibAvatar = (ImageButton) this
- .findViewById(com.android.dialer.R.id.zj_detail_avatar);
- byte[] photo = getPhoto(contactId);
- if (photo != null) {
- Bitmap map = BitmapFactory.decodeByteArray(photo, 0, photo.length);
-
- int scaleWidth = 110;
- int scaleHeight = 110;
- Bitmap bitmap = Bitmap.createScaledBitmap(map, scaleWidth,
- scaleHeight, true);
-
- ibAvatar.setImageBitmap(bitmap);
- }
- }
52.调整Activity跳转动画的速度
改一下duration,500到300
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android" >
- <translate
- android:duration="300"
- android:fromXDelta="0"
- android:toXDelta="100%p" />
- </set>
53.联系人列表标星Tag显示★而不是字母逻辑:
-
- String mfirstLetter = PinyinUtils
- .getPingYin(Utils.mPersons.get(position).mName).substring(0, 1)
- .toUpperCase();
- String zjContactIdStr = Utils.mPersons.get(position).mID;
- boolean isStar = isStarred(zjContactIdStr);
- String firstLetter;
- Log.e("zjStar",
- "position" + position + "\tcontactId"
- + Utils.mPersons.get(position).mContactId + "\tName:"
- + Utils.mPersons.get(position).mName + "\tisStar:"
- + isStar);
- if (isStar) {
- firstLetter = "☆";
- } else {
- firstLetter = notAlpha(mfirstLetter);
- }
54.联系人标星Tag去重(多个标星归档只显示一个Tag)逻辑
-
- if (position == 0) {
- myViews.letterTag.setVisibility(View.VISIBLE);
- myViews.letterTag.setText(firstLetter);
- } else {
- if (isStar) {
- myViews.letterTag.setVisibility(View.GONE);
- } else {
-
- String mfirstLetterPre = PinyinUtils
- .getPingYin(Utils.mPersons.get(position - 1).mName)
- .substring(0, 1).toUpperCase();
- String firstLetterPre = notAlpha(mfirstLetterPre);
-
- if (firstLetter.equals(firstLetterPre)) {
- myViews.letterTag.setVisibility(View.GONE);
- } else {
- myViews.letterTag.setVisibility(View.VISIBLE);
- myViews.letterTag.setText(firstLetter);
- }
- }
- }
55.获得汉语拼音首字母
- private String notAlpha(String str) {
- if (str == null) {
- return "#";
- }
- if (str.trim().length() == 0) {
- return "#";
- }
-
- Pattern pattern = Pattern.compile("^[A-Za-z]+$");
- if (pattern.matcher(str).matches()) {
- return (str).toUpperCase();
- } else {
- return "#";
- }
- }
56.
联系人列表右侧快速定位字母条监听
-
- private class ScrollBarListener implements
- AlphabetScrollBar.OnTouchBarListener {
- @Override
- public void onTouch(String letter) {
- if (letter.compareTo("☆") == 0) {
- m_contactslist.setSelection(0);
- } else if (letter.compareTo("#") == 0) {
- int zjCount = m_contactslist.getChildCount();
- m_contactslist.setSelection(zjCount);
- } else {
-
- int idx = Utils.binarySearch(letter);
- if (idx != -1) {
- m_contactslist.setSelection(idx);
- }
- }
- }
- }
57.搜索联系人过滤器
- public void FilterSearch(String keyword) {
- mFilterList.clear();
-
- for (int i = 0; i < Utils.mPersons.size(); i++) {
-
- boolean isSearchNum = Utils.mPersons.get(i).mNum == null ? false
- : (Utils.mPersons.get(i).mNum.indexOf(keyword) > 0);
- if (isSearchNum
- || isStrInString(Utils.mPersons.get(i).mPY, keyword)
- || Utils.mPersons.get(i).mName.contains(keyword)
- || isStrInString(Utils.mPersons.get(i).mFisrtSpell, keyword)) {
-
- SortEntry entry = new SortEntry();
- entry.mName = Utils.mPersons.get(i).mName;
- entry.mID = Utils.mPersons.get(i).mID;
- entry.mOrder = i;
- entry.mPY = Utils.mPersons.get(i).mPY;
- entry.mNum = Utils.mPersons.get(i).mNum;
- mFilterList.add(entry);
- }
- }
- }
58.长按多选联系人群发短信逻辑
- 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++) {
-
-
- 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);
-
-
-
-
-
-
-
-
- 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) {
- }
- }
到此问题解决的差不多了,明天再写一篇估计就可以完结这个系列。以后遇到问题再补充,有不明白的地方欢迎交流。
今天就到这儿吧,学习的脚步不能停止,加油。
完结篇~
今天工作感觉挺累的,就没有加班在,早早的溜回来,看了会儿蓝牙的资料。不知不觉都9点了,开始~
59.B应用要用A应用的Activity2,但Activity2依赖于A应用的Activity1,也就是说Activity2要使用Activity1处理后的数据,这时候可以让B应用跳转到一个Activity3,Activity3和Activity1内容相同,但是在onResume中写下跳转到Activity2的逻辑:
- protected void onResume() {
-
- super.onResume();
- Intent intent = new Intent(this, MultiChoiseSecond.class);
- startActivity(intent);
- finish();
- }
60.加快拨号面板号码匹配响应时间
-
-
- public void afterTextChanged(Editable input) {
-
-
-
-
-
- inputstring = input.toString();
-
- mHandler.postDelayed(mrunnable, 100);
- }
61.加快三个应用间Activity的跳转速度
- android:launchMode="singleTask"
62.让应用不显示在最近运行程序列表中
在主activity处设置属性:
- android:excludeFromRecents=“true”
63.解决页面之间跳转时的短暂黑屏问题
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <style name="activityTheme" parent="@android:style/Theme">
- <item name="android:windowIsTranslucent">true</item> (zj:这一个item就够了)
- </style>
- </resources>
64.最小化应用(注释代码为杀死应用)
-
-
-
-
-
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addCategory(Intent.CATEGORY_HOME);
- startActivity(intent);
65.获取Log
权限:
- <uses-permission android:name=”android.permission.READ_LOGS” />
- new Thread(new Runnable()
- {
- @Override
- public void run()
- {
- Process logcatProcess = null;
- BufferedReader bufferedReader = null;
- try
- {
-
- logcatProcess = Runtime.getRuntime().exec(new String[] {“logcat”, “ActivityManager:I *:S”});
- bufferedReader = new BufferedReader(new InputStreamReader(logcatProcess.getInputStream()));
-
- String line;
-
- while ((line = bufferedReader.readLine()) != null)
- {
- if (line.indexOf(“cat=[android.intent.category.HOME]“) > 0)
- {
- Session.exit();
- }
- }
-
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }).start();
今天的内容相对较少,目前项目还存在一些待优化的问题,以后再跟进补充。
66.通话记录ListView实现左滑发短信和右滑打电话
下午公司篮球赛最后一场,超神队一分憾败。可惜,不过比赛归比赛,重要的是过程中的精彩。
通话记录向左滑动发短信,向右滑动打电话,微信电话本上有这个很便捷的操作,在项目的修改过程中,就仿造微信的交互方式,实现了ListView左右滑动,今天总结一下:
同样由于是在源码环境下编译,所以代码中的资源引用之类地方的可能和常规的稍微不同。
-
- @Override
- public void removeItem(RemoveDirection direction, int position) {
- String sildeNum = callLogs.get(position).getNumber();
-
- switch (direction) {
- case RIGHT:
-
- tvTopBar.setBackgroundColor(Color.parseColor("#454545"));
- tvTopBar.setText(com.android.dialer.R.string.call_log_activity_title);
- RecordSlideListView.itemView.setBackgroundColor(Color
- .parseColor("#ffffff"));
- Uri uri = Uri.parse("tel:" + sildeNum);
- Intent intent = new Intent(Intent.ACTION_CALL, uri);
- startActivity(intent);
- break;
- case LEFT:
-
-
-
- tvTopBar.setBackgroundColor(Color.parseColor("#454545"));
- tvTopBar.setText(com.android.dialer.R.string.call_log_activity_title);
- RecordSlideListView.itemView.setBackgroundColor(Color
- .parseColor("#ffffff"));
- Uri uri2 = Uri.parse("smsto:" + sildeNum);
- Intent intent2 = new Intent(Intent.ACTION_SENDTO, uri2);
- startActivity(intent2);
- break;
-
- default:
- break;
- }
- }
自定义组件SlideListView:
- package com.android.dialer.calllog;
-
- import android.content.Context;
- import android.graphics.Color;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.VelocityTracker;
- import android.view.View;
- import android.view.ViewConfiguration;
- import android.view.WindowManager;
- import android.widget.AdapterView;
- import android.widget.ListView;
- import android.widget.Scroller;
- import android.widget.TextView;
-
- public class RecordSlideListView extends ListView {
-
-
- private int slidePosition;
- private int downY;
- private int downX;
- private int screenWidth;
- public static View itemView;
- private Scroller scroller;
- private static final int SNAP_VELOCITY = 300;
- private VelocityTracker velocityTracker;
- private boolean isSlide = false;
- private int mTouchSlop;
- private RemoveListener mRemoveListener;
- private RemoveDirection removeDirection;
-
- public enum RemoveDirection {
- RIGHT, LEFT;
- }
-
- public RecordSlideListView(Context context) {
- this(context, null);
- }
-
- public RecordSlideListView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public RecordSlideListView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- screenWidth = ((WindowManager) context
- .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
- .getWidth();
- scroller = new Scroller(context);
- mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- }
-
- public void setRemoveListener(RemoveListener removeListener) {
- this.mRemoveListener = removeListener;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN: {
- addVelocityTracker(event);
-
- if (!scroller.isFinished()) {
- return super.dispatchTouchEvent(event);
- }
- downX = (int) event.getX();
- downY = (int) event.getY();
-
- slidePosition = pointToPosition(downX, downY);
-
- if (slidePosition == AdapterView.INVALID_POSITION) {
- return super.dispatchTouchEvent(event);
- }
-
- itemView = getChildAt(slidePosition - getFirstVisiblePosition());
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY
- || (Math.abs(event.getX() - downX) > mTouchSlop && Math
- .abs(event.getY() - downY) < mTouchSlop)) {
- isSlide = true;
- }
- break;
- }
- case MotionEvent.ACTION_UP:
- recycleVelocityTracker();
- break;
- }
-
- return super.dispatchTouchEvent(event);
- }
-
- private void scrollRight() {
-
-
-
-
-
-
- removeDirection = RemoveDirection.RIGHT;
- final int delta = (screenWidth + itemView.getScrollX());
- scroller.startScroll(itemView.getScrollX(), 0, -delta, 0,
- Math.abs(delta));
- postInvalidate();
- }
-
-
- private void scrollLeft() {
-
- removeDirection = RemoveDirection.LEFT;
- final int delta = (screenWidth - itemView.getScrollX());
- scroller.startScroll(itemView.getScrollX(), 0, delta, 0,
- Math.abs(delta));
- postInvalidate();
- }
-
- private void scrollByDistanceX() {
- if (itemView.getScrollX() >= screenWidth / 3) {
- scrollLeft();
- } else if (itemView.getScrollX() <= -screenWidth / 3) {
- scrollRight();
- } else {
- itemView.scrollTo(0, 0);
-
- itemView.setBackgroundColor(Color.parseColor("#ffffff"));
- Record.tvTopBar.setBackgroundColor(Color.parseColor("#454545"));
- Record.tvTopBar
- .setText(com.android.dialer.R.string.call_log_activity_title);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (isSlide && slidePosition != AdapterView.INVALID_POSITION) {
-
- addVelocityTracker(ev);
- final int action = ev.getAction();
- int x = (int) ev.getX();
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- int deltaX = downX - x;
- downX = x;
-
- if (deltaX > 20) {
- itemView.setBackgroundColor(Color.parseColor("#D1EEEE"));
- Record.tvTopBar.setBackgroundColor(Color
- .parseColor("#1C86EE"));
- Record.tvTopBar
- .setText(com.android.dialer.R.string.zj_slide_left_to_sms);
-
- } else if (deltaX < -20) {
- itemView.setBackgroundColor(Color.parseColor("#D1EEEE"));
- Record.tvTopBar.setBackgroundColor(Color
- .parseColor("#32CD32"));
- Record.tvTopBar
- .setText(com.android.dialer.R.string.zj_slide_right_to_call);
-
- }
-
- itemView.scrollBy(deltaX, 0);
- return true;
-
- case MotionEvent.ACTION_UP:
- int velocityX = getScrollVelocity();
- if (velocityX > SNAP_VELOCITY) {
- scrollRight();
- } else if (velocityX < -SNAP_VELOCITY) {
- scrollLeft();
- } else {
- scrollByDistanceX();
- }
-
- recycleVelocityTracker();
- isSlide = false;
- break;
- }
-
- return true;
- }
- return super.onTouchEvent(ev);
- }
-
- @Override
- public void computeScroll() {
- if (scroller.computeScrollOffset()) {
- itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY());
-
- postInvalidate();
-
- if (scroller.isFinished()) {
- if (mRemoveListener == null) {
- throw new NullPointerException(
- "RemoveListener is null, we should called setRemoveListener()");
- }
-
- itemView.scrollTo(0, 0);
- mRemoveListener.removeItem(removeDirection, slidePosition);
- }
- }
- }
-
-
- private void addVelocityTracker(MotionEvent event) {
- if (velocityTracker == null) {
- velocityTracker = VelocityTracker.obtain();
- }
-
- velocityTracker.addMovement(event);
- }
-
-
- private void recycleVelocityTracker() {
- if (velocityTracker != null) {
- velocityTracker.recycle();
- velocityTracker = null;
- }
- }
-
-
- private int getScrollVelocity() {
- velocityTracker.computeCurrentVelocity(1000);
- int velocity = (int) velocityTracker.getXVelocity();
- return velocity;
- }
-
-
- public interface RemoveListener {
- public void removeItem(RemoveDirection direction, int position);
- }
-
- }
代码有点长,Adapter的就先不贴了。
67.黑名单来电拦截自动挂断
准备工作:
添加一个名为android.telephony的包,里面有个NeighboringCellInfo.aidl,内容如下:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package android.telephony;
-
- parcelable NeighboringCellInfo;
新建包名为com.android.internal.telephony的包,新建文件ITelephony.aidl,文件内容如下:
广播:
-
-
-
- package com.android.dialer.calllog;
-
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
-
- public class BlacklistBroadcast extends BroadcastReceiver{
-
- @Override
- public void onReceive(Context context, Intent intent) {
-
-
- if (intent.getAction().equals(
- Intent.ACTION_NEW_OUTGOING_CALL)){
- }
- else{
- Intent Sbintent = new Intent(context,com.android.dialer.calllog.BlacklistService.class);
- context.startService(Sbintent);
- }
- }
-
- }
DbHelper:
-
-
-
- package com.android.dialer.calllog;
-
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
-
- public class BlacklistDbHelper extends SQLiteOpenHelper{
- final String CREATE_TABLE_SQL =
- "create table blacklist(_id integer primary key autoincrement , number text)";
- public BlacklistDbHelper(Context context, String name,
- CursorFactory factory, int version) {
- super(context, name, factory, version);
-
- }@Override
- public void onCreate(SQLiteDatabase db) {
-
- db.execSQL(CREATE_TABLE_SQL);
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
-
- }
-
- public Cursor getCursorByNumber(String number) {
- String selectQuery = "SELECT * FROM blacklist where number = "+number;
-
- SQLiteDatabase db = this.getReadableDatabase();
- Cursor cursor = db.rawQuery(selectQuery, null);
- return cursor;
- }
-
-
- }
Service:
-
-
-
- package com.android.dialer.calllog;
-
- import java.lang.reflect.Method;
-
- import com.android.internal.telephony.ITelephony;
- import android.app.Service;
- import android.content.Intent;
- import android.database.Cursor;
- import android.os.IBinder;
- import android.telephony.PhoneStateListener;
- import android.telephony.TelephonyManager;
-
- public class BlacklistService extends Service {
- BlacklistDbHelper dbHelper = new BlacklistDbHelper(this, "blacklist.db",
- null, 1);
- TelephonyManager tManager;
- CustomPhoneCallListener cpListener;
-
- public class CustomPhoneCallListener extends PhoneStateListener {
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- switch (state) {
- case TelephonyManager.CALL_STATE_IDLE:
- break;
- case TelephonyManager.CALL_STATE_OFFHOOK:
- break;
- case TelephonyManager.CALL_STATE_RINGING:
- System.out.println("this is 1");
- if (isBlock(incomingNumber)) {
- System.out.println("this is 2");
- try {
- Method method = Class.forName(
- "android.os.ServiceManager").getMethod(
- "getService", String.class);
- IBinder binder = (IBinder) method.invoke(null,
- new Object[] { TELEPHONY_SERVICE });
- ITelephony telephony = ITelephony.Stub
- .asInterface(binder);
- telephony.endCall();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- break;
-
- }
- super.onCallStateChanged(state, incomingNumber);
- }
-
- public boolean isBlock(String number) {
- Cursor cursor = dbHelper.getReadableDatabase().rawQuery(
- "select * from blacklist", null);
- while (cursor.moveToNext()) {
- if (cursor.getString(1).equals(number)) {
- return true;
- }
- }
- return false;
- }
- }
-
- @Override
- public IBinder onBind(Intent arg0) {
-
- return null;
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
-
- tManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
- cpListener = new CustomPhoneCallListener();
- tManager.listen(cpListener, PhoneStateListener.LISTEN_CALL_STATE);
- super.onStart(intent, startId);
- }
-
- }
ListView:
-
-
-
- package com.android.dialer.calllog;
-
- import java.util.ArrayList;
- import java.util.List;
-
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.Intent;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.net.Uri;
- import android.os.Bundle;
- import android.provider.CallLog;
- import android.provider.Contacts;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.Toast;
- import android.app.ActionBar;
-
- public class BlacklistView extends Activity {
-
- public int version = Integer.valueOf(android.os.Build.VERSION.SDK);
- BlacklistDbHelper dbHelper;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
-
- super.onCreate(savedInstanceState);
- setContentView(com.android.dialer.R.layout.zj_blacklist_result);
- dbHelper = new BlacklistDbHelper(this, "blacklist.db", null, 1);
- final ListView listview = (ListView) findViewById(com.android.dialer.R.id.zj_blacklist_view);
- listview.setAdapter(new ArrayAdapter<String>(this,
- com.android.dialer.R.layout.zj_blacklist_item, getData()));
-
- TextView tvHint = (TextView) findViewById(com.android.dialer.R.id.zj_balcklist_hint);
- TextView tvEmpty = (TextView) findViewById(com.android.dialer.R.id.zj_blacklist_empty);
-
- if (getData().isEmpty()) {
-
-
- tvEmpty.setVisibility(View.VISIBLE);
- tvHint.setVisibility(View.GONE);
-
-
-
-
-
- } else {
- tvEmpty.setVisibility(View.GONE);
- tvHint.setVisibility(View.VISIBLE);
- }
- listview.setOnItemClickListener(new OnItemClickListener() {
-
- @Override
- public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
- long arg3) {
- String phoneNum = arg0.getItemAtPosition(arg2).toString();
- dbHelper.getReadableDatabase().execSQL(
- "delete from blacklist where number = ?",
- new String[] { phoneNum });
- onCreate(null);
-
- }
- });
-
-
- ActionBar actionBar = getActionBar();
- actionBar.setHomeButtonEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
-
- }
-
- private List<String> getData() {
- List<String> data = new ArrayList<String>();
- Cursor cursor = dbHelper.getReadableDatabase().rawQuery(
- "select * from blacklist", null);
- while (cursor.moveToNext()) {
- data.add(cursor.getString(1));
- }
- cursor.close();
-
- return data;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
-
- getMenuInflater().inflate(com.android.dialer.R.menu.zj_blacklist_view,
- menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- finish();
-
- if (version > 5) {
- overridePendingTransition(
- com.android.dialer.R.anim.zj_right_in,
- com.android.dialer.R.anim.zj_right_out);
- }
-
- break;
-
- case com.android.dialer.R.id.zj_blacklist_clear:
- dbHelper.getReadableDatabase().execSQL("delete from blacklist");
- onCreate(null);
- break;
-
- default:
- break;
- }
- return true;
- }
-
- }
操作:
- case com.android.dialer.R.id.zj_add_blacklist:
-
- BlacklistDbHelper dbHelper = new BlacklistDbHelper(this,
- "blacklist.db", null, 1);
-
- boolean isBlack = isNumBlack(number);
-
- if (isBlack) {
- Toast.makeText(this, com.android.dialer.R.string.zj_alredy_add,
- Toast.LENGTH_SHORT).show();
- } else {
- dbHelper.getReadableDatabase().execSQL(
- "insert into blacklist values(null , ?)",
- new String[] { number });
- ibAddBlack.setBackgroundDrawable(getResources().getDrawable(
- com.android.dialer.R.drawable.zj_block_red));
- Toast.makeText(this,
- com.android.dialer.R.string.zj_add_blacklist_ok,
- Toast.LENGTH_SHORT).show();
- }
- break;
-
- public boolean isNumBlack(String number) {
- BlacklistDbHelper dbHelper = new BlacklistDbHelper(this,
- "blacklist.db", null, 1);
- Cursor countCur = dbHelper.getCursorByNumber(number);
- int numCount = 0;
- try {
- numCount = countCur.getCount();
- Log.e("numCount", "" + numCount);
-
- } catch (Exception e) {
-
- } finally {
- countCur.close();
- }
- if (numCount > 0)
- return true;
- else
- return false;
-
- }
-
- public void zjAddBlack(View v) {
- BlacklistDbHelper dbHelper = new BlacklistDbHelper(this,
- "blacklist.db", null, 1);
- boolean isBlack = isNumBlack(number);
- if (isBlack) {
-
- dbHelper.getReadableDatabase().execSQL(
- "delete from blacklist where number = ?",
- new String[] { number });
- ibAddBlack.setBackgroundDrawable(getResources().getDrawable(
- com.android.dialer.R.drawable.zj_block_grey));
- isBlack = false;
- Toast.makeText(this,
- com.android.dialer.R.string.zj_del_blacklist_ok,
- Toast.LENGTH_SHORT).show();
-
- } else if (!isBlack) {
-
- dbHelper.getReadableDatabase().execSQL(
- "insert into blacklist values(null , ?)",
- new String[] { number });
- ibAddBlack.setBackgroundDrawable(getResources().getDrawable(
- com.android.dialer.R.drawable.zj_block_red));
- isBlack = true;
- Toast.makeText(this,
- com.android.dialer.R.string.zj_add_blacklist_ok,
- Toast.LENGTH_SHORT).show();
- }
- }
67.来电界面InCallUI的布局修改:
有个客户要让来电界面适应他们提供的皮套,这样的话,就要根据皮套的开窗来调节来电界面。而来电界面并不是在Dialer代码中,而是在pacakage/apps/InCallUI中,调节对应的布局文件。
编译的时候也要注意,不可以单独模块编译InCallUI,模块编译Dialer就会把InCallUI编译进去了。
packages/apps/InCallUI/res/layout/primary_call_info.xml