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

论坛 期权论坛 脚本     
匿名技术用户   2021-1-2 09:52   18   0

之前看到自己的手机应用突然会弹出一个提示框感到有点神奇,不知道是怎么做到的,后面才了解到是后台服务弹的。后台服务弹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 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP