2 zhongyuanceshi zhongyuanceshi 于 2012.12.02 21:28 提问

如何在Android4.0.4锁屏界面的电话图标右上角显示未接电话个数?

目前,未接电话个数也要获取到。存在的问题就是如何在电话图标右上角显示未接电话个数?
电话图标是控件MultiWaveView上的图标,该类是系统已经定义好的。我想通过直接集成View来自定义自己的View,然后在OnDraw函数通过Canvas和paint,指定坐标来画。但始终是没有显示出来。自定义view的OnDraw函数也有跑到。请指教要实现这效果,该怎样是画未接个数呢?效果图:enter image description here
我是在自定义的handler中调用构造函数。每10s就会handler处理。

private final Handler mUpdateMissCallNum = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "mUpdateMissCallNum");
switch (msg.what) {
case UPDATESTART:

Log.i(TAG, "UPDATESTART");
sNewMissedCallCount = getMissedCallCount(mContext);
if (sNewMissedCallCount != sTempMissedCallCount)
{

Log.i(TAG, "sNewMissedCallCount != sTempMissedCallCount");
new Thread(new Runnable()
{
public void run()
{

Log.i(TAG, "sNewMissedCallCount is:"+sNewMissedCallCount);

Log.i(TAG, "sTempMissedCallCount is:"+sTempMissedCallCount);
sTempMissedCallCount = sNewMissedCallCount;
mMissedCallView=new MissedCallView(mContext,sTempMissedCallCount);
Log.i(TAG, "sTempMissedCallCount is:"+sTempMissedCallCount);
        }
        }
    ).start();
    }
    break;
    default:
    break;
    }
}
}

mMissedCallView=new MissedCallView(mContext,sTempMissedCallCount);这就是我调用自定义view的地方。通过直接用坐标和canvas,paint画,不要再在xml文件里去写吧。
锁屏用到的xml文件:Keyguardscreentabunlock.xml (framework\base\core\res\res\layout)该文件中用系统自定义的波纹锁屏

<com.android.internal.widget.multiwaveview.MultiWaveView
android:id="@+id/unlockwidget"
android:orientation="horizontal"
android:layoutwidth="matchparent"
android:layoutheight="matchparent"
android:layout_alignParentBottom="true"
        android:targetDrawables="@array/lockscreen_targets_with_camera"
        android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
        android:directionDescriptions="@array/lockscreen_direction_descriptions"
        android:handleDrawable="@drawable/ic_lockscreen_handle"
        android:waveDrawable="@drawable/ic_lockscreen_outerring"
        android:outerRadius="@dimen/multiwaveview_target_placement_radius"
        android:snapMargin="@dimen/multiwaveview_snap_margin"
        android:hitRadius="@dimen/multiwaveview_hit_radius"
        android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
        android:horizontalOffset="0dip"
        android:verticalOffset="60dip"
        android:feedbackCount="3"
        android:vibrationDuration="20"
        />

效果图:enter image description here
我们只是把相机改成了拨号,就是在这拨号图标上打算画上未接电话数。请指教,谢谢!
这个类存放位置:framework\base\core\java\com\android\internal\widget\multiwaveview\MissedCallView.java

public class MissedCallView extends View {

private static final String TAG = "MissedCallViews";

public static final int UPDATESTART = 10;

private static final int DELAYTIME = 10000;

private int sTempMissedCallCount=-1;

Context mContext;

Canvas mCanvas;

public MissedCallView(Context context) 
{

super(context);

Log.i(TAG, "MissedCallView1");

mCanvas=new Canvas();

}

public MissedCallView(Context context, AttributeSet attrs)
{ 
super(context, attrs);

Log.i(TAG, "MissedCallView2");

mCanvas=new Canvas();

}

public MissedCallView(Context context,int missedCallNum) {

super(context);

sTempMissedCallCount=missedCallNum;

Log.i(TAG, "MissedCallView3");

mCanvas=new Canvas();

}

@Override 
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if(sTempMissedCallCount>0)

{

Paint paint=new Paint(Paint.ANTIALIASFLAG); 
paint.setColor(Color.RED); Log.i(TAG,"Integer.toString(sTempMissedCallCount)is:"+Integer.toString(sTempMissedCallCount)); canvas.drawText(Integer.toString(sTempMissedCallCount),40,310,paint);//50 invalidate();

Log.i(TAG, "invalidate");

}

}

} 

这是自定义view。只跑了 这个构造函数MissedCallView(Context context,int missedCallNum)。是在我定义的public class MissCallObserver extends ContentObserver监听未接电话个数类中调用的。为什么没有跑onDraw函数?请指教。未接电话个数获取是正确的。关键是显示了。

20个回答

u010616022
u010616022   2013.05.08 14:54
已采纳

布局使用FrameLayout,将电话图标控件放下面,默认显示,未接个数控件放上面,默认隐藏;
逻辑采用ContentObserver监听电话数据库的变化,数据变化时查询数据库,得到未接电话个数

ce_la_vie
ce_la_vie   2012.12.03 11:35

可以用标记flagFLAG_SHOW_WHEN_LOCKED实现

public static final int FLAG_SHOW_WHEN_LOCKED

添加到API 5中

flag: 当屏幕被锁时显示指定标记,这会让应用窗口优先于其他窗口,可以用`FLAG_KEEP_SCREEN_ON`打开屏幕,在keyguard之前直接显示窗口,用`FLAG_DISMISS_KEYGUARD`自动解除keyguard。

在图片中显示2这个数量:

在系统设置中设置alarm字符串

String message = "2";
Settings.System.putString(context.getContentResolver(),
        Settings.System.NEXT_ALARM_FORMATTED, message);

补充:

需要查询未接电话的个数,然后在Cursor获取查询到的总数:

String[] projection = { CallLog.Calls.CACHED_NAME, CallLog.Calls.CACHED_NUMBER_LABEL, CallLog.Calls.TYPE };
       String where = CallLog.Calls.TYPE+"="+CallLog.Calls.MISSED_TYPE;          
       Cursor c = this.getContentResolver().query(CallLog.Calls.CONTENT_URI, selection,where, null, null);
       c.moveToFirst();    
       Log.d("CALL", ""+c.getCount()); //其他操作
        if(c.getCount() == SOME_VALUE_TO_START_APP_ONE)

在where语句中,设置选择数据的条件,根据你的需求,应该是CallLog.Calls.MISSED_TYPE

还可以选择来电的名字,号码,家庭工作什么的。

表达式和SQL查询语句是等价的,比如:

SELECT CACHED_NAME, CACHED_NUMBER_LABEL, TYPE FROM CONTENT_URI WHERE TYPE=MISSED_TYPE

android锁屏的说明:http://code.google.com/p/mylockforandroid/wiki/LockActivity

ce_la_vie
ce_la_vie 不好意思,现在不能上qq。我在答案中给你加了一个锁屏的连接,你看一下
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 你好,有看到链接。还是不怎么清楚用到解决我的问题。请指教?我加了233393756这个CSDNask,我是:zhongyuanceshi-android,不知道你有没有加,是哪位?
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 未接电话数我已经求得。没看懂是怎样用flag:FLAG_SHOW_WHEN_LOCKED。请问大概流程?
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 谢谢ce_la_vie的回复,但没看懂如何用FLAG。未接电话数应该要放在一个控件中吧。请问大概流程是什么?未接电话数以求得。谢谢!
大约 5 年之前 回复
franzhong
franzhong   2012.12.03 18:08

如果我理解不错的话,你是想自绘View
你把问题理清楚,就两点关健地方,
1:取得未接电话条数
2:将这个int型变量显示
问题(1)可参考下面代码:

private void findNewCallCount(){     
        Cursor  csr = null;     
        int missedCallCount = 0;   
        try {     
            csr = getContentResolver().query(Calls.CONTENT_URI, new String[]{Calls.NUMBER,Calls.TYPE,Calls.NEW},   
                    null,null,Calls.DEFAULT_SORT_ORDER);     
            if(null != csr){   
                while(csr.moveToNext()){   
                    int type = csr.getInt(csr.getColumnIndex(Calls.TYPE));   
                    switch (type){   
                        case Calls.MISSED_TYPE:   
                            if(csr.getInt(csr.getColumnIndex(Calls.NEW)) == ){   
                                missedCallCount++;   
                            }   
                            break;   
                        case Calls.INCOMING_TYPE:   
                            break;   
                        case Calls.OUTGOING_TYPE:   
                            break;   
                    }   
                }   
            }   
        } catch (Exception e) {     
            e.printStackTrace();     
        } finally {     
            csr.close();     
        }     
        newCallCount = missedCallCount;//未读电话数目     
    }

问题(2)关于canvas显示问题
这样就可以把字写上去了
//canvas.drawText("123条记录", x, y, mPaint);//xy坐标
你的view是怎么写的,可以log调试分析呀。
你想立既显示,却未公布你相关代码,我猜肯定是未刷新造成的
当有新的未接电话,立马刷新canvas,刷新方式多样
invalidate或者postinvalindate()都能调用onDraw函数还有矩形区域设置等地方需
注意,你可以搜"android canvas refresh"
你需要一个单独线程跟踪或是启动个service监听。

franzhong
franzhong 先回答2:了解为啥会不停的调用,默认不会这样。是否有线程run?1:值不对,检查是哪些地方可以改它的值,一是初始化地方,二是其他地方,例如,赋值时就传的是-1,是否有这种可能?好在问题朝前进方向发展,现在就是一个值的问题了,你该学学如何调试程序,要不很是麻烦
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 嗯。把if(sTempMissedCallCount>0)去掉重新编译后发现:log一直在打印:Num is:-1 Integer.toString(sTempMissedCallCount) is:-1 invalidate这三条语句,也就是ondraw函数中的。但界面没有看到显示。存在问题:1:ondraw函数中获取的sTempMissedCallCount值不对,不是未接电话个数,始终为-1.2:没有显示,而是不停的调用ondraw函数。
大约 5 年之前 回复
franzhong
franzhong 有跑到,上面你跟我这样说的"遗憾的事还是没有跑onDraw函数",关于锁屏的事你可以了解: boolean inKeyguardRestrictedInputMode();对问题要举一反三啊,问题是无穷不尽的,解决一下问题要明白怎么回事,多想一下,下一个问题你就能自已解决了
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 有跑到onDraw方法,但是是在熄屏之后(这之前处于解锁。熄屏后也锁屏了),此时Num is:-1.跑了构造函数2:MissedCallView2,而不是从调用的构造函数3传过来的值,所以没有if判断应该会显示-1的。请问:这是什么原因导致的,而没有只要是锁屏界面就显示呢?
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 嗯。你的建议很好。之前我是有在FM模块自定义过View的,也显示OK。请问:你用我代码是放在锁屏源码下调试吗?我仅仅在MultiWaveView.java的onDraw画采用同样方法画是可以显示的(这仅是验证,但不是我要的效果应该这个要锁屏后才显示)。还是自己写了一个Activity的Demo调试的?
大约 5 年之前 回复
franzhong
franzhong 在我这是好着的,你别纠结这些事了,不熟悉的话调试也慢,你重写个view类玩玩,花他个一两小时,搞明白了再来看这块,要不你头都晕了,效率不高还出不来;
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 遗憾的事还是没有跑onDraw函数。分别在3个构造函数末尾及public void run() 函数末尾添加mMissedCallView.invalidate();及invalidate()后,都没有画出来。
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 有添加:@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(TAG, "Num is:"+sTempMissedCallCount); 我先在三个构造函数末尾加上invalidate编译再试试。
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi invalidate这个函数调用,要在view中才能调用吧,否则报错。我在构造函数 MissedCallView(Context context,int missedCallNum)调用invalidate刷新可以吗?还是在哪个地方比较好?
大约 5 年之前 回复
franzhong
franzhong 你刷新一下就可以了,无论何时刷新都会被调用。 invalidate();
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi onDraw函数始终没有跑到,没画成功,还请指教。继承view的重载函数onDraw应该不用我们自己显示调用吧,系统会自己调用(上面大错字了),跑了构造函数,按理说就启动了这个自定义VIew吧?
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 非常感谢你的解疑答覆。按照你上面的建议。onDraw函数始终没有跑到。构造函数有跑到:MissedCallView3 sTempMissedCallCount is:1。这也可以看出未接电话传过来也是对的。继承view的重载函数onDraw应该是用我们自己显示调用吧,系统会调用。
大约 5 年之前 回复
franzhong
franzhong 并且,调用的时候应先调用初始化missedCallNum的那个构造,可看log是否输出MissedCallView3;再在你的onDraw的if条件前面加个Log,如果没进条件里,你还以为未执行呢。加上这句Log.i(TAG, "Num is:"+sTempMissedCallCount);有这些信息你就能明白原因出在哪儿了
大约 5 年之前 回复
franzhong
franzhong 哦,我已知晓,你的paint为啥那样的,你先注释后改为Paint mPaint = new Paint();
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 获取未接电话数是OK。关键是显示不了。我是在源码基础上修改的。自定义MissedCallView代码见上面。谢谢!
大约 5 年之前 回复
cytown
cytown   2012.12.06 11:56

MultiWaveView 接受的是Drawable, 所以最简单的方法是更改为新的BitmapDrawable,里面包含电话的icon和未接电话数,然后MultiWaveView.postInvalidate即可。

cytown
cytown 使用postInvalidate().
大约 5 年之前 回复
cytown
cytown 你要用handler去执行mMultiWaveView.invalidate(),在callback里面不能调用UI变更
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 在文件KeyguardStatusViewManager.java (framework\base\policy\src\com\android\internal\policy\impl)中的, private phoneStateCallback mPhoneCallback = new phoneStateCallback(){ public void onPhoneStateChanged(int phoneState) {加入mMultiWaveView.invalidate();。(有电话就会跑这里).编译后开机不了。请cytown给完整的代码。我试了很多方法都不行。
大约 5 年之前 回复
cytown
cytown 当触发新的来电什么的时候,要通知MultiWaveView去invalidate.
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 有尝试仅仅在MultiWaveView.java中文件中处理,包括:获取电话数以及在onDraw方法中直接用Canva和Paint指定坐标画出未接个数,但是只有在熄屏后(锁屏了)再点亮,才看到刷新画上了。而没有不管什么情况下,只要是亮屏锁屏状态就及时显示。还请 cytown指教,你的方法具体是怎样实现?
大约 5 年之前 回复
zhongyuanceshi
zhongyuanceshi 最简单的方法是更改为新的BitmapDrawable.------你的意思是不用自定义View?请问该如何更改为新的BitmapDrawable?并且把未接电话数和电话Icon绑在一起?谢谢
大约 5 年之前 回复
huangsheng8090
huangsheng8090   2013.09.16 22:20

有点意思 .......

u012741496
u012741496 有点意思
接近 4 年之前 回复
chinesepengkai
chinesepengkai 有点意思
大约 4 年之前 回复
u012829933
u012829933   2013.11.13 21:29

不知道 不知道怎么办

u013139405
u013139405   2013.12.13 14:56

在设置里面找一找,一般都在那里面的。

u013417251
u013417251   2014.01.08 14:13

先注释后改为Paint mPaint = new Paint(); franzhong

u012889565
u012889565   2014.03.12 11:50

private void findNewCallCount(){

Cursor csr = null;

int missedCallCount = 0;

try {

csr = getContentResolver().query(Calls.CONTENT_URI, new String[]{Calls.NUMBER,Calls.TYPE,Calls.NEW},

null,null,Calls.DEFAULT_SORT_ORDER);

if(null != csr){

while(csr.moveToNext()){

int type = csr.getInt(csr.getColumnIndex(Calls.TYPE));

switch (type){

case Calls.MISSED_TYPE:

if(csr.getInt(csr.getColumnIndex(Calls.NEW)) == ){

missedCallCount++;

}
break;

case Calls.INCOMING_TYPE:

break;

case Calls.OUTGOING_TYPE:

break;

}

}

}

} catch (Exception e) {

e.printStackTrace();

} finally {

csr.close();

}

newCallCount = missedCallCount;//未读电话数目

}

wyr972951027
wyr972951027   2014.05.20 21:22

使用FrameLayout,将电话图标控件放下面,默认为显示,未接个数控件放上面,默认是隐藏;
逻辑采用ContentObserver监听电话数据库的变化,数据变化时查询数据库,得到未接电话个数

共20条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!