项目中需要用到通知栏进度条,查找了好多资料、链接如下:
- Android 为Notification加上一个进度条
- Android实现Service后台下载Notification进度条
- Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
- android service startService bindService
- Android中BindService方式使用的理解
- [Android 机制] 大家帮忙看一下这个BUG.
- Android 的service的定义可以 作为内部类使用吗?
我先简后难写了两种实现,第一个没有使用服务,activity转向后台进度条消失;另一个使用服务,activity转向后台进度条仍然继续。
以下是第一个实现:
主界面布局代码 notify.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas./apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <Button
- android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="开始" />
-
- </LinearLayout>
通知栏内容布局代码 notify_content.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas./apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
-
- <ProgressBar
- android:id="@+id/progressBar1"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_marginTop="14dp"
- android:layout_toRightOf="@+id/imageView1" />
-
- <TextView
- android:id="@+id/textView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_below="@+id/progressBar1"
- android:layout_marginRight="26dp"/>
-
- <ImageView
- android:id="@+id/imageView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/textView1"
- android:layout_alignParentLeft="true"
- android:src="@drawable/ic_launcher" />
-
- </RelativeLayout>
AndroidManifest.xml 代码添加如下:
- <activity
- android:label="@string/app_name"
- android:name=".notify.NotificationActivity1" >
- <intent-filter >
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
主程序NotificationActivity1.java代码如下:
- package com.zhang.new_test.notify;
-
- 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.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.RemoteViews;
- import android.widget.Toast;
-
- import com.zhang.new_test.R;
-
- public class NotificationActivity1 extends Activity implements OnClickListener {
-
- private static final int NOTIFICATION_ID = 0x12;
- private Notification notification = null;
- private NotificationManager manager = null;
- private int _progress = 0;
- private boolean isStop = false;
-
- @Override
- protected void onPause() {
- isStop = false;
- manager.cancel(NOTIFICATION_ID);
-
- super.onPause();
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.notify);
-
- Button btn = (Button) findViewById(R.id.button1);
- btn.setOnClickListener(this);
- notification = new Notification(R.drawable.sg, "带进条的提醒", System.currentTimeMillis());
-
- notification.contentView = new RemoteViews(getApplication().getPackageName(), R.layout.notify_content);
- notification.contentView.setProgressBar(R.id.progressBar1, 100, 0, false);
- notification.contentView.setTextViewText(R.id.textView1, "进度" + _progress + "%");
-
- notification.contentIntent = PendingIntent.getActivity(this, 0,new Intent(this, NotificationActivity1.class), 0);
-
- manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-
- }
-
- @Override
- public void onClick(View v) {
- isStop = true;
- manager.notify(NOTIFICATION_ID, notification);
- new ProgressThread().start();
- }
-
- private class ProgressThread extends Thread {
-
- @Override
- public void run() {
- while (isStop) {
- _progress += 10;
- Message msg = handler.obtainMessage();
- msg.arg1 = _progress;
- msg.sendToTarget();
-
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- public Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- notification.contentView.setProgressBar(R.id.progressBar1, 100, msg.arg1, false);
- notification.contentView.setTextViewText(R.id.textView1, "进度" + msg.arg1 + "%");
- manager.notify(NOTIFICATION_ID, notification);
-
- if (msg.arg1 == 100) {
- _progress = 0;
- manager.cancel(NOTIFICATION_ID);
- isStop = false;
- Toast.makeText(NotificationActivity1.this, "下载完毕", 1000).show();
- }
- }
- };
- }
以下是第二个实现:
主界面布局代码 notify.xml和通知栏内容布局代码 notify_content.xml同上一个实现
AndroidManifest.xml 代码添加如下:
- <activity
- android:label="@string/app_name"
- android:name=".notify.NotificationActivity2" >
- <intent-filter >
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
- <service android:name=".notify.NotificationActivity2$DownLoadService"/>
主程序NotificationActivity2.java代码如下:
- package com.zhang.new_test.notify;
-
- import android.app.Activity;
- import android.app.Notification;
- import android.app.NotificationManager;
- import android.app.PendingIntent;
- import android.app.Service;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Binder;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.RemoteViews;
- import android.widget.Toast;
-
- import com.zhang.new_test.R;
-
- public class NotificationActivity2 extends Activity implements OnClickListener {
-
- private DownLoadService downLoadService;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.notify);
-
- Button btn = (Button) findViewById(R.id.button1);
- btn.setOnClickListener(this);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- Intent serviceIntent = new Intent(this,DownLoadService.class);
- startService(serviceIntent);
- bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unbindService(serviceConnection);
- }
-
- @Override
- public void onClick(View v) {
- downLoadService.startDownLoad();
- }
-
- private ServiceConnection serviceConnection = new ServiceConnection() {
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service){
- downLoadService = ((DownLoadService.DownLoadServiceBinder) service).getService();
- Toast.makeText(NotificationActivity2.this, "Service Connected.", Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- }
- };
-
- public static class DownLoadService extends Service {
-
- private static final int NOTIFICATION_ID = 0x12;
- private Notification notification = null;
- private NotificationManager manager = null;
- private int _progress = 0;
- private boolean isStop = false;
-
- private Binder serviceBinder = new DownLoadServiceBinder();
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- notification = new Notification(R.drawable.sg, "带进条的提醒", System.currentTimeMillis());
-
- notification.contentView = new RemoteViews(getApplication().getPackageName(), R.layout.notify_content);
- notification.contentView.setProgressBar(R.id.progressBar1, 100, 0, false);
- notification.contentView.setTextViewText(R.id.textView1, "进度" + _progress + "%");
-
- notification.contentIntent = PendingIntent.getActivity(this, 0,new Intent(this, NotificationActivity1.class), 0);
-
- manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return serviceBinder;
- }
-
- @Override
- public void onDestroy() {
- isStop = false;
- manager.cancel(NOTIFICATION_ID);
-
- super.onDestroy();
- }
-
- public void startDownLoad() {
- isStop = true;
- manager.notify(NOTIFICATION_ID, notification);
- new ProgressThread().start();
- }
-
- public class DownLoadServiceBinder extends Binder {
- public DownLoadService getService() {
- return DownLoadService.this;
- }
- }
-
- private class ProgressThread extends Thread {
-
- @Override
- public void run() {
- while (isStop) {
- _progress += 10;
- Message msg = handler.obtainMessage();
- msg.arg1 = _progress;
- msg.sendToTarget();
-
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- public Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- notification.contentView.setProgressBar(R.id.progressBar1, 100, msg.arg1, false);
- notification.contentView.setTextViewText(R.id.textView1, "进度" + msg.arg1 + "%");
- manager.notify(NOTIFICATION_ID, notification);
-
- if (msg.arg1 == 100) {
- _progress = 0;
- manager.cancel(NOTIFICATION_ID);
- isStop = false;
- Toast.makeText(DownLoadService.this, "下载完毕", 1000).show();
- }
- }
- };
- }
- }
效果我就不贴图了,前面提到的链接中有,效果差不多。
接下来分析一下代码,第二个和第一个最大区别是引入了service,这样可以支持后台运行,所以第二个更有实用性。但是刚开始写代码,不应该引入服务,那样会带来过多的复杂度,出bug时很难调试,写完第一个在重构引入服务就没那么麻烦了,大部分代码可以复用的。
主要知识点就是Notification和bindService的使用,我主要遇到两个悲剧,和大家分享一下:
- 忘了unbindService,抛了一个不知道的异常,链接6解决了
- .notify.NotificationActivity2$DownLoadService 我写成了 .notify.NotificationActivity2.DownLoadService,链接7解决了,这个花了半天时间,我就不相信这个会错,主要是因为写代码时new 静态内部类时都是用 . 啊,忘了配置是用的反射,所以应该用 $ 啊,主要是以前没写过静态内部类的反射,记住教训了。
希望这篇博文对大家有帮助。