后台应用服务弹自定义Toast框

     之前看到自己的手机应用突然会弹出一个提示框感到有点神奇,不知道是怎么做到的,后面才了解到是后台服务弹的。后台服务弹Toast框其实跟Activity界面差不多,下面先来看看项目SimpleJarService结构:

├── AndroidManifest.xml
├── Android.mk
├── libs
│  ├── android-support-v4.jar
│  ├── fw.jar
│  └── simple.jar
├── res
│  ├── drawable
│  │  └── common_toast_bg.xml
│  ├── drawable-hdpi
│  │  └── ic_launcher.png
│  ├── drawable-ldpi
│  ├── drawable-mdpi
│  │  └── ic_launcher.png
│  ├── drawable-xhdpi
│  │  └── ic_launcher.png
│  ├── layout
│  │  └── common_toast_custom.xml
│  ├── values
│  │  ├── colors.xml
│  │  ├── strings.xml
│  │  └── styles.xml
│  ├── values-v11
│  │  └── styles.xml
│  └── values-v14
│      └── styles.xml
└── src
    └── com
        └── china
            └── service
                ├── BootReceiverBroadcast.java
                ├── Logger.java
                ├── SimpleControl.java
                └── SimpleService.java

       SimpleJarService项目在《在Android系统中实现AIDL 自定义对象传递》文章中有介绍,现在主要是在SimpleControl.java类实现实现弹Toast框的方法,而SimpleControl.java类是在SimpleService.java中实例化的。如下:

package com.china.service;

import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.china.jar.VoiceChangedListener;
import com.chinatsp.service.R;

public class SimpleControl {
	private static VoiceChangedListener changedListener;
	private static Context mContext;
	public SimpleControl(VoiceChangedListener voiceChangedListener, Context context){
		changedListener = voiceChangedListener;
		mContext = context;
	}
	
	//获取初始化后的回调实例
	public static VoiceChangedListener getVoiceCallBack(){
		return changedListener;
	}
	
	static long lastshowToastTime = 0;
	public static void showToast(String s) {
		if(Math.abs(System.currentTimeMillis() - lastshowToastTime)<3000){
			return; //如果两次要求弹Toast框的时间间隔小于3秒,就不执行第二次弹框
		}
		Logger.d("show Toast");
		View view = LayoutInflater.from(mContext.getApplicationContext())
				.inflate(R.layout.common_toast_custom,
						null);
		WindowManager wm = (WindowManager) mContext.getApplicationContext()
				.getSystemService(Context.WINDOW_SERVICE);
		int width = wm.getDefaultDisplay().getWidth();
		LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
				width / 2, ViewGroup.LayoutParams.WRAP_CONTENT);

		TextView txt = (TextView) view
				.findViewById(R.id.textViewToastMsg);
		txt.setText(s);
		txt.setLayoutParams(layoutParams);
		Toast toast = new Toast(mContext.getApplicationContext());
		toast.setView(view);
		toast.setGravity(Gravity.CENTER, 0, 0);
		toast.setDuration(3000);
		toast.show();
		lastshowToastTime = System.currentTimeMillis();
	}
}
package com.china.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;

import com.china.jar.IVoiceCallBackInterface;
import com.china.jar.IVoiceClientInterface;
import com.china.jar.StudentInfo;
import com.china.jar.VoiceChangedListener;
import com.china.jar.VoiceManager;

public class SimpleService extends Service{
	private static VoiceClientInterfaceImpl mBinder;
	@Override
	public IBinder onBind(Intent intent) {
		Logger.d();
		return mBinder;//跟客户端绑定
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		Logger.d();
		if (null == mBinder){
			initService();
		}
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Logger.d();
		if (null == mBinder){
			initService();
		}
		return START_STICKY;
	}
	
	//实现AIDL的接口
	private class VoiceClientInterfaceImpl extends IVoiceClientInterface.Stub{
		protected RemoteCallbackList<IVoiceCallBackInterface> mRemoteCallbackList = 
				new RemoteCallbackList<IVoiceCallBackInterface>();
		private SimpleControl control;
		
		public VoiceClientInterfaceImpl(){
			control = new SimpleControl(voiceChangedListener, SimpleService.this);//实例化SimpleControl对象
		}
		
		@Override
		public void face() throws RemoteException {
			Logger.d("face----excute!");//客户端调用face方法时这里会执行,会打印face----excute!
		}
		
		//注册回调
		@Override
		public void registerCallBack(IVoiceCallBackInterface arg0)
				throws RemoteException {
			Logger.d();
			mRemoteCallbackList.register(arg0);
			
		}

		//注销回调
		@Override
		public void unRegisterCallBack(IVoiceCallBackInterface arg0)
				throws RemoteException {
			Logger.d();
			mRemoteCallbackList.unregister(arg0);
		}
		
		//调用回调方法
		private VoiceChangedListener voiceChangedListener = new VoiceChangedListener() {
		
			@Override
			public void openAppByVoice(String arg0) {
				Logger.d("arg0 = " + arg0);
				int len = mRemoteCallbackList.beginBroadcast();
				for (int i = 0; i <len; i++) {
					try {
						mRemoteCallbackList.getBroadcastItem(i).openAppByVoice(arg0);
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				}
				mRemoteCallbackList.finishBroadcast();
			}
		};

		@Override
		public void registerUser(StudentInfo studentInfo) throws RemoteException {
			Logger.d("name = " + studentInfo.getName() + " ,age = " + studentInfo.getAge());
			
		}
	}
	//初始化服务,主要是向系统注册服务
	private void initService(){
		Logger.d();
		if (null == mBinder){
			synchronized (SimpleService.class) {
				if (null == mBinder){
					try {
						mBinder = new VoiceClientInterfaceImpl();
						ServiceManager.addService(VoiceManager.NAME, mBinder);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	
	
}

 可以看到SimpleControl实例化放到了SimpleService类中的内部类VoiceClientInterfaceImpl中实例化,其实也可以放到onCreate()方法中实例化,由于该项目之前是用于aidl的功能实现,所以会放到VoiceClientInterfaceImpl类中实例化。

common_toast_custom.xml是自定义一个布局,用于规范Toast的大小及风格,具体如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialogAera"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/common_toast_bg"
    android:clickable="true"
    android:gravity="center"
    android:minHeight="285.0px"
    android:minWidth="871.0px"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textViewToastMsg"
        style="@style/shadowStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:singleLine="true"
        android:textColor="@color/common_text_dark"
        android:textSize="28sp" />

</LinearLayout>

      通过发送接收广播的方式来测试showToast(String s)方法的功能。具体实现如下:

package com.china.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class BootReceiverBroadcast extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Logger.d();
        Intent service = new Intent(context, SimpleService.class);//开机启动会拉起服务SimpleService
        context.startService(service);
        if(intent.getAction().equals("android.intent.gunder.SimpleJar")){
        	//android.intent.gunder.SimpleJar属于自定义action
        	Logger.d(intent.getAction());
        	SimpleControl.getVoiceCallBack().openAppByVoice("nihao");//这里模拟调用penAppByVoice方法
        	SimpleControl.showToast("你好,我是Service里面的Toast!");//这里模拟调用showToast方法
        }
    }
}

测试结果如下:

 

 

代码参考:https://github.com/gunder1129/android-tool/tree/master/AIDLdemo/SimpleJarService

 

      

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值