Android Dialer,Mms,Contacts源码修改笔记

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 比如 -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”>

44.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES

这样的问题主要是签名冲突造成的,比如你使用了ADB的debug权限签名,但后来使用标准sign签名后再安装同一个文件会出现这样的错误提示,解决的方法除了只有先老老实实从手机上卸载原有版本再进行安装,而adb install -r参数也无法解决这个问题。

45.cp命令移动隐藏文件

-a参数 所有文件,包括隐藏文件

-r参数 移动目录

所以备份时,直接cp -a -r 一步到位,省得一些点文件漏操作。

46.去除应用图标

去掉Manifest中Activity的对应标签:

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) {

// Cursor cur = getContentResolver().query( // Raw Contacts表

// ContactsContract.RawContacts.CONTENT_URI, null,

// “contact_id = ?”, new String[] { “”+contactId }, null);

String lookupkey = “”;

// final Uri dataUri = Uri.withAppendedPath(

// ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId),

// Contacts.Data.CONTENT_DIRECTORY);

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);

//intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

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) {

// 以下代码将字节数组转化成Bitmap对象,然后再ImageView中显示出来

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);

// 调整大小 START

int scaleWidth = 110;

int scaleHeight = 110;

Bitmap bitmap = Bitmap.createScaledBitmap(map, scaleWidth,

scaleHeight, true);

// 调整大小 END

ibAvatar.setImageBitmap(bitmap); // 参数由原来的map换成转换过的bitmap

}

}

52.调整Activity跳转动画的速度

改一下duration,500到300

<?xml version="1.0" encoding="utf-8"?>

<translate

android:duration=“300”

android:fromXDelta=“0”

android:toXDelta=“100%p” />

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)逻辑

// 如果是第1个联系人 那么letterTag始终要显示

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);

}

}

}

private String notAlpha(String str) {

if (str == null) {

return “#”;

}

if (str.trim().length() == 0) {

return “#”;

}

// 正则表达式,判断首字母是否是英文字母

Pattern pattern = Pattern.compile(“1+$”);

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();

// 遍历mArrayList

for (int i = 0; i < Utils.mPersons.size(); i++) {

// 如果遍历到List包含所输入字符串

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)) {

// 将遍历到的元素重新组成一个list

SortEntry entry = new SortEntry();

entry.mName = Utils.mPersons.get(i).mName;

entry.mID = Utils.mPersons.get(i).mID;

entry.mOrder = i; // 在原Cursor中的位置

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 ops = new ArrayList();

for (int i = 0; i < ChooseContactsID.size(); i++) {

// ops.add(ContentProviderOperation.newDelete(Uri.withAppendedPath(RawContacts.CONTENT_URI,

// ChooseContactsID.get(i))).build());

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);

/*

  • try { getContentResolver()

  • .applyBatch(ContactsContract.AUTHORITY, ops);

  • //Log.e(“ZJSmsCount”, “” + ChooseContactsID.size()); } catch

  • (RemoteException e) { // TODO Auto-generated catch block

  • e.printStackTrace(); } catch (OperationApplicationException e) {

  • // TODO Auto-generated catch block e.printStackTrace(); }

*/

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() {

// TODO Auto-generated method stub

super.onResume();

Intent intent = new Intent(this, MultiChoiseSecond.class);

startActivity(intent);

finish();

}

60.加快拨号面板号码匹配响应时间

// at com.android.dialer.dialpad.DialpadFragment.java

public void afterTextChanged(Editable input) {

// When DTMF dialpad buttons are being pressed, we delay

// SpecialCharSequencMgr sequence,

// since some of SpecialCharSequenceMgr’s behavior is too abrupt for the

// “touch-down”

// behavior.

inputstring = input.toString();

// mHandler.postDelayed(mrunnable, 2000);//czq

mHandler.postDelayed(mrunnable, 100); // zj

}

61.加快三个应用间Activity的跳转速度

android:launchMode=“singleTask”

62.让应用不显示在最近运行程序列表中

在主activity处设置属性:

android:excludeFromRecents=“true”

63.解决页面之间跳转时的短暂黑屏问题

<?xml version="1.0" encoding="utf-8"?>

64.最小化应用(注释代码为杀死应用)

// Intent intent = new Intent(Intent.ACTION_MAIN);

// intent.addCategory(Intent.CATEGORY_HOME);

// intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

// startActivity(intent);

// android.os.Process.killProcess(android.os.Process.myPid());

Intent intent = new Intent(Intent.ACTION_MAIN);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.addCategory(Intent.CATEGORY_HOME);

startActivity(intent);

65.获取Log

权限:

new Thread(new Runnable()

{

@Override

public void run()

{

Process logcatProcess = null;

BufferedReader bufferedReader = null;

try

{

/** 获取系统logcat日志信息 */

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(); // zj:获取滑动Item的号码

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:

// Toast.makeText(this, "向左短信 "+ position,

// Toast.LENGTH_SHORT).show();

// rlRecordBack.setBackgroundColor(Color.parseColor(“#1C86EE”));

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() {

// tvTopBar =

// (TextView)findViewById(com.android.dialer.R.id.textViewRecord);

// tvTopBar.setBackgroundColor(Color.parseColor(“#32CD32”));

// tvTopBar.setText(com.android.dialer.R.string.zj_slide_right_to_call);

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);

// zj:恢复Topbar的字和背景颜色

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) { // 向左sms #D1EEEE

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) { // 向右call

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; // 拖动的时候ListView不滚动

// break;

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,内容如下:

/* //device/java/android/android/content/Intent.aidl

**

** Copyright 2007, The Android Open Source Project

**

** Licensed under the Apache License, Version 2.0 (the “License”);

** you may not use this file except in compliance with the License.

** You may obtain a copy of the License at

**

** http://www.apache.org/licenses/LICENSE-2.0

**

** Unless required by applicable law or agreed to in writing, software

** distributed under the License is distributed on an “AS IS” BASIS,

** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

** See the License for the specific language governing permissions and

** limitations under the License.

*/

package android.telephony;

parcelable NeighboringCellInfo;

新建包名为com.android.internal.telephony的包,新建文件ITelephony.aidl,文件内容如下:

/*

  • Copyright © 2007 The Android Open Source Project

  • Licensed under the Apache License, Version 2.0 (the “License”);

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at

  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an “AS IS” BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.

*/

package com.android.internal.telephony;

import android.os.Bundle;

import java.util.List;

import android.telephony.NeighboringCellInfo;

/**

  • Interface used to interact with the phone. Mostly this is used by the

  • TelephonyManager class. A few places are still using this directly.

  • Please clean them up if possible and use TelephonyManager insteadl.

  • {@hide}

*/

interface ITelephony {

/**

  • Dial a number. This doesn’t place the call. It displays

  • the Dialer screen.

  • @param number the number to be dialed. If null, this

  • would display the Dialer screen with no number pre-filled.

*/

void dial(String number);

/**

  • Place a call to the specified number.

  • @param number the number to be called.

*/

void call(String number);

/**

  • If there is currently a call in progress, show the call screen.

  • The DTMF dialpad may or may not be visible initially, depending on

  • whether it was up when the user last exited the InCallScreen.

  • @return true if the call screen was shown.

*/

boolean showCallScreen();

/**

  • Variation of showCallScreen() that also specifies whether the

  • DTMF dialpad should be initially visible when the InCallScreen

  • comes up.

  • @param showDialpad if true, make the dialpad visible initially,

  •                otherwise hide the dialpad initially.
    
  • @return true if the call screen was shown.

  • @see showCallScreen

*/

boolean showCallScreenWithDialpad(boolean showDialpad);

/**

  • End call or go to the Home screen

  • @return whether it hung up

*/

boolean endCall();

/**

  • Answer the currently-ringing call.

  • If there’s already a current active call, that call will be

  • automatically put on hold. If both lines are currently in use, the

  • current active call will be ended.

  • TODO: provide a flag to let the caller specify what policy to use

  • if both lines are in use. (The current behavior is hardwired to

  • “answer incoming, end ongoing”, which is how the CALL button

  • is specced to behave.)

  • TODO: this should be a oneway call (especially since it’s called

  • directly from the key queue thread).

*/

void answerRingingCall();

/**

  • Silence the ringer if an incoming call is currently ringing.

  • (If vibrating, stop the vibrator also.)

  • It’s safe to call this if the ringer has already been silenced, or

  • even if there’s no incoming call. (If so, this method will do nothing.)

  • TODO: this should be a oneway call too (see above).

  •   (Actually *all* the methods here that return void can
    
  •   probably be oneway.)
    

*/

void silenceRinger();

/**

  • Check if we are in either an active or holding call

  • @return true if the phone state is OFFHOOK.

*/

boolean isOffhook();

/**

  • Check if an incoming phone call is ringing or call waiting.

  • @return true if the phone state is RINGING.

*/

boolean isRinging();

/**

  • Check if the phone is idle.

  • @return true if the phone state is IDLE.

*/

boolean isIdle();

/**

  • Check to see if the radio is on or not.

  • @return returns true if the radio is on.

*/

boolean isRadioOn();

/**

  • Check if the SIM pin lock is enabled.

  • @return true if the SIM pin lock is enabled.

*/

boolean isSimPinEnabled();

/**

  • Cancels the missed calls notification.

*/

void cancelMissedCallsNotification();

/**

  • Supply a pin to unlock the SIM. Blocks until a result is determined.

  • @param pin The pin to check.

  • @return whether the operation was a success.

*/

boolean supplyPin(String pin);

/**

  • Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated

  • without SEND (so dial is not appropriate).

  • @param dialString the MMI command to be executed.

  • @return true if MMI command is executed.

*/

boolean handlePinMmi(String dialString);

/**

  • Toggles the radio on or off.

*/

void toggleRadioOnOff();

/**

  • Set the radio to on or off

*/

boolean setRadio(boolean turnOn);

/**

  • Request to update location information in service state

*/

void updateServiceLocation();

/**

  • Enable location update notifications.

*/

void enableLocationUpdates();

/**

  • Disable location update notifications.

*/

void disableLocationUpdates();

/**

  • Enable a specific APN type.

*/

int enableApnType(String type);

/**

  • Disable a specific APN type.

*/

int disableApnType(String type);

/**

  • Allow mobile data connections.

*/

boolean enableDataConnectivity();

/**

  • Disallow mobile data connections.

*/

boolean disableDataConnectivity();

/**

  • Report whether data connectivity is possible.

*/

boolean isDataConnectivityPossible();

Bundle getCellLocation();

/**

  • Returns the neighboring cell information of the device.

*/

List getNeighboringCellInfo();

int getCallState();

int getDataActivity();

int getDataState();

}

广播:

/*

  • Add By ZJ For Blacklist

*/

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) {

// TODO Auto-generated method stub

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:

/*

  • Add By ZJ For Blacklist

*/

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);

// TODO Auto-generated constructor stub

}@Override

public void onCreate(SQLiteDatabase db) {

// TODO Auto-generated method stub

db.execSQL(CREATE_TABLE_SQL);

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

// TODO Auto-generated method stub

}

//zj add START

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;

}

//zj add END

}

Service:

/*

  • Add By ZJ For Blacklist

*/

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) {

// TODO Auto-generated method stub

return null;

}

@Override

public void onStart(Intent intent, int startId) {

// TODO Auto-generated method stub

tManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);

cpListener = new CustomPhoneCallListener();

tManager.listen(cpListener, PhoneStateListener.LISTEN_CALL_STATE);

super.onStart(intent, startId);

}

}

ListView:

/*

  • Add By ZJ For Blacklist

*/

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; // for ActionBar

public class BlacklistView extends Activity {

public int version = Integer.valueOf(android.os.Build.VERSION.SDK);

BlacklistDbHelper dbHelper;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

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(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()) {

// Toast.makeText(BlacklistView.this, “暂无黑名单”, 5000).show();

tvEmpty.setVisibility(View.VISIBLE);

tvHint.setVisibility(View.GONE);

// Intent intent = new Intent(BlacklistView.this,

// com.android.dialer.calllog.BlacklistChoice.class);

结尾

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

t 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; // for ActionBar

public class BlacklistView extends Activity {

public int version = Integer.valueOf(android.os.Build.VERSION.SDK);

BlacklistDbHelper dbHelper;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

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(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()) {

// Toast.makeText(BlacklistView.this, “暂无黑名单”, 5000).show();

tvEmpty.setVisibility(View.VISIBLE);

tvHint.setVisibility(View.GONE);

// Intent intent = new Intent(BlacklistView.this,

// com.android.dialer.calllog.BlacklistChoice.class);

结尾

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

[外链图片转存中…(img-Jd6cxhji-1714274258916)]

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

[外链图片转存中…(img-3Db0eQER-1714274258917)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


  1. A-Za-z ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值