小左闲谈

NBA篮球国度武汉站看汤神

In 生活  @2015-08-24

我其实并不追星,但NBA巨星真来了,刚好周末又没啥事,就去逛逛咯,也算给每天的学习放松一下,汤神就不用多说了吧,单节37分的表现在NBA那都是排的上号的,最佳SG与哈登有得一拼。怀着一种膜拜大神的心情,我就坐上了去传说中的异地——汉口的地铁。
汤神和巴恩斯展示冠军奖杯
汤神和巴恩斯展示冠军奖杯
汤神你这样盯着真的好吗?
汤神你这样盯着真的好吗? (更多…)

错误:java.lang.IllegalArgumentException: Service not registered

In 学习, 笔记  @2015-08-20

问题

在做Service的绑定和解绑小项目测试的时候,绑定成功,解绑也成功,但是如果解除绑定后再点击给解除绑定的指令(项目中就是点击按钮解除绑定),会报这个错误:

AndroidRuntime(7090): java.lang.IllegalArgumentException: Service not registered: 
com.m1910.servicetest.MainActivity$1@41ddfcc0

错误提示Service没有注册,事实上我在Manifest.xml中已经注册过这个Service了。

修改前代码:

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.start_service:
            Intent startIntent = new Intent(this, MyService.class);
            startService(startIntent);// 启动服务
            break;
        case R.id.stop_service:
            Intent stopIntent = new Intent(this, MyService.class);
            stopService(stopIntent);// 停止服务
            break;
        case R.id.bind_service:
            Intent bindIntent = new Intent(this, MyService.class);
                        // 绑定服务
            bindService(bindIntent, connection, BIND_AUTO_CREATE);
            break;
        case R.id.unbind_service:
            unbindService(connection);// 解绑服务   
            break;
        default:
            break;
        }
    }

原因

查询官方文档中关于unbindService()这个方法的介绍:

public abstract void unbindService (ServiceConnection conn)

Added in API level 1
Disconnect from an application service. You will no longer receive calls as the service is restarted, and the service is now allowed to stop at any time.

Parameters
conn    The connection interface previously supplied to bindService(). This parameter must not be null.

最后一句看到这个传入的conn参数不能为null,也就是必须有绑定存在,才能解绑,小项目中绑定成功后第一次点击解绑不会报错,解绑后这个参数就是null了,再次点击解绑就会报错,那么我们为解绑加一个判断就可以了。

修改后代码如下:

private boolean isBound = false;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.start_service:
            Intent startIntent = new Intent(this, MyService.class);
            startService(startIntent);// 启动服务
            break;
        case R.id.stop_service:
            Intent stopIntent = new Intent(this, MyService.class);
            stopService(stopIntent);// 停止服务
            break;
        case R.id.bind_service:
            Intent bindIntent = new Intent(this, MyService.class);
                        // 绑定服务
            isBound = bindService(bindIntent, connection, BIND_AUTO_CREATE);
            break;
        case R.id.unbind_service:
            if (isBound) {
                unbindService(connection);// 解绑服务
                isBound = false;
            }
            break;
        default:
            break;
        }
    }

网上也有人用getApplicationContext().unbindService(mConnection);这样来做,什么意思我也不太懂,不过最终效果一样也是要加一个是否为空的判断。

Android笔记:Notification的使用总结

In 学习, 笔记  @2015-08-19

关于Android通知栏Notification使用的总结。

重点知识点:

  • 使用Notification.builder类的系列set方法设置通知栏的参数;
  • setContentIntent()方法添加PendingIntent达到点击启动Activity的功能。
  • 调用builder.build()方法返回一个notification对象;
  • 然后利用notification的一些属性设置它的声音,震动,灯光,点击关闭等等特性。
    Android通知栏Notification使用的总结

notification点击后消失两种方法:

  1. 在点击启动的新Activity中调用notificationManager.cancel();
  2. 给notification.flags = Notification.FLAG_AUTO_CANCEL;

notification常驻状态栏的两个flag

  1. FLAG_ONGOING_EVENT //提示用户程序正在运行,如正在通话……
  2. FLAG_NO_CLEAR //clear按钮将无法清除这个notification

案例代码:

package com.m1910.notificationtest;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

    private Button sendNotice;
    String tickerText = "This is ticker text.";
    String contentTitle = "This is content title.";
    String contentText = "This is content Text.";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendNotice = (Button) findViewById(R.id.send_notice);
        sendNotice.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.send_notice:
            // 实例化一个NotificationManager对象。
            NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            // 创建intent用来启动NotificationActivity
            Intent intent = new Intent(this, NotificationActivity.class);
            // 将intent传入到PendingIntent对象中用getActivity()方法实例化一个PendingIntent对象。
            // 这里还可以使用getService()以及getBroadcast()方法,传入的参数一样。
            PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
            // 实例化一个Builder对象。
            Notification.Builder nBuilder = new Notification.Builder(this);
            // 利用Builder对象的一系列set方法设置参数,其中注意使用setContentIntent()传入上面的PendingIntent对象pi;
            // builder()方法返回一个Notification对象
            Notification notification = nBuilder.setContentTitle(contentTitle).setContentText(contentText)
                    .setTicker(tickerText).setSmallIcon(R.drawable.ic_launcher).setContentIntent(pi).build();
            // 设置提示音
            notification.defaults = Notification.DEFAULT_SOUND;
            // 设置点击后自动清除通知
            notification.flags = Notification.FLAG_AUTO_CANCEL;
            // 调用NotificationManager的notify()方法启动这个notification;
            // 第一个参数APP中这个notification唯一标识符,第二个是要显示的Notification对象。
            manager.notify(1, notification);
            break;
        default:
            break;
        }
    }
}

Notification进阶部分:

  1. 如网易云音乐那样的可操作的通知栏需要用到相对比较复杂的布局使用Notification.BuildersetContent(RemoteViews views)设置自定义布局,暂时还没做过;
  2. android4.1之后,有小布局,大布局,下滑后的通知栏,选中的状态栏,以及锁屏状态的通告,这些都是可以深入研究的方向。
  3. 前台服务的使用,创建服务的时候调用startForeground()方法启动notification,让服务在状态栏常驻。
标签: , , , ,   评论: 8枚