Quellcode durchsuchen

AndroidAppProcess不好用

zengjiebin vor 7 Jahren
Ursprung
Commit
514970185c

+ 3 - 0
app/build.gradle

@@ -249,6 +249,9 @@ dependencies {
     //极光
     compile files('libs/jcore-android-1.2.0.jar')
     compile files('libs/jpush-android-3.1.2.jar')
+    //获取其它应用运行情况
+
+    compile 'com.jaredrummler:android-processes:1.1.1'
 
 }
 static def releaseTime() {

+ 8 - 4
app/src/main/AndroidManifest.xml

@@ -16,9 +16,11 @@
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS"
+        tools:ignore="ProtectedPermissions"/>
     <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
+        tools:ignore="ProtectedPermissions"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 
@@ -43,13 +45,15 @@
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <uses-permission android:name="android.permission.GET_TASKS"/>
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
-    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
+        tools:ignore="ProtectedPermissions"/>
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
     <!--必须的权限配置-->
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.READ_LOGS" />
+    <uses-permission android:name="android.permission.READ_LOGS"
+        tools:ignore="ProtectedPermissions"/>
     <!--保存资源到SD卡-->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <!-- 推荐的权限 -->

+ 0 - 62
app/src/main/java/com/sheep/gamegroup/hook/InstrumentationProxy.java

@@ -1,62 +0,0 @@
-package com.sheep.gamegroup.hook;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-
-import com.sheep.gamegroup.util.LogUtil;
-
-import java.lang.reflect.Method;
-
-/**
- * Created by realicing on 2018/6/26.
- * realicing@sina.com
- */
-public class InstrumentationProxy extends Instrumentation {
-
-
-    public static final String TAG = "InstrumentationProxy";
-    public static final String EXEC_START_ACTIVITY = "execStartActivity";
-
-    // ActivityThread里面原始的Instrumentation对象,这里千万不能写成mInstrumentation,这样写  
-    //抛出异常,已亲测试,所以这个地方就要注意了  
-    public Instrumentation oldInstrumentation;
-
-    //通过构造函数来传递对象  
-    public InstrumentationProxy(Instrumentation mInstrumentation) {
-        oldInstrumentation = mInstrumentation;
-    }
-
-
-    //这个方法是由于原始方法里面的Instrumentation有execStartActivity方法来定的  
-    public Instrumentation.ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
-                                                            Intent intent, int requestCode, Bundle options) {
-        LogUtil.println(TAG, "\n打印调用startActivity相关参数: \n" + "who = [" + who + "], " +
-                "\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +
-                "\ntarget = [" + target + "], \nintent = [" + intent +
-                "], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]");
-
-
-        LogUtil.println(TAG, "------------hook  success------------->");
-        LogUtil.println(TAG, "这里可以做你在打开StartActivity方法之前的事情");
-        LogUtil.println(TAG, "------------hook  success------------->");
-        LogUtil.println(TAG, "");
-
-        //由于这个方法是隐藏的,所以需要反射来调用,先找到这方法  
-        try {
-            Method execStartActivity = Instrumentation.class.getDeclaredMethod(
-                    EXEC_START_ACTIVITY,
-                    Context.class, IBinder.class, IBinder.class, Activity.class,
-                    Intent.class, int.class, Bundle.class);
-            execStartActivity.setAccessible(true);
-            return (ActivityResult) execStartActivity.invoke(oldInstrumentation, who,
-                    contextThread, token, target, intent, requestCode, options);
-        } catch (Exception e) {
-            //如果你在这个类的成员变量Instrumentation的实例写错mInstrument,代码讲会执行到这里来  
-            throw new RuntimeException("if Instrumentation paramerter is mInstrumentation, hook will fail");
-        }
-    }
-}  

+ 0 - 10
app/src/main/java/com/sheep/gamegroup/model/entity/AppInfo.java

@@ -22,10 +22,8 @@ public class AppInfo {
     //存储的位置.
     private boolean isSD;
 
-
     private String packageName;
 
-    private String className;
 
     public String getPackageName() {
         return packageName;
@@ -35,14 +33,6 @@ public class AppInfo {
         this.packageName = packageName;
     }
 
-    public String getClassName() {
-        return className;
-    }
-
-    public void setClassName(String className) {
-        this.className = className;
-    }
-
     public Drawable getIcon() {
         return icon;
     }

+ 55 - 0
app/src/main/java/com/sheep/gamegroup/model/entity/AppUsage.java

@@ -0,0 +1,55 @@
+package com.sheep.gamegroup.model.entity;
+
+import org.xutils.db.annotation.Column;
+import org.xutils.db.annotation.Table;
+
+import java.io.Serializable;
+
+/**
+ * Created by realicing on 2018/5/11.
+ */
+@Table(name = "app_usage")
+public class AppUsage implements Serializable {
+
+    @Column(name = "package_name", isId = true)
+    private String packageName;
+    @Column(name = "lastTimeStamp")
+    private long lastTimeStamp;
+    @Column(name = "firstTimeStamp")
+    private long firstTimeStamp;
+    @Column(name = "totalTimeInForeground")
+    private long totalTimeInForeground;
+
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public long getLastTimeStamp() {
+        return lastTimeStamp;
+    }
+
+    public void setLastTimeStamp(long lastTimeStamp) {
+        this.lastTimeStamp = lastTimeStamp;
+    }
+
+    public long getFirstTimeStamp() {
+        return firstTimeStamp;
+    }
+
+    public void setFirstTimeStamp(long firstTimeStamp) {
+        this.firstTimeStamp = firstTimeStamp;
+    }
+
+    public long getTotalTimeInForeground() {
+        return totalTimeInForeground;
+    }
+
+    public void setTotalTimeInForeground(long totalTimeInForeground) {
+        this.totalTimeInForeground = totalTimeInForeground;
+    }
+}

+ 18 - 0
app/src/main/java/com/sheep/gamegroup/model/util/AutoTaskListUtil.java

@@ -27,6 +27,9 @@ public class AutoTaskListUtil {
 
     private static AutoTaskListUtil autoTaskListUtil = new AutoTaskListUtil();
 
+    private AutoTaskListUtil(){
+        resetReceiveTaskTime();
+    }
     public static AutoTaskListUtil getInstance(){
         if (autoTaskListUtil == null){
             autoTaskListUtil = new AutoTaskListUtil();
@@ -152,5 +155,20 @@ public class AutoTaskListUtil {
     public boolean isShowing() {
         return tipToOpernAccessibilityDialog != null && tipToOpernAccessibilityDialog.isShowing();
     }
+    //正在运行的app没有变化,即传入的包名与lastAppRecord中的包名相同
+    public boolean isLastAppRecord(String packageName) {
+        return lastAppRecord != null && TextUtils.equals(packageName, lastAppRecord.getPackageName());
+    }
+
+
+
+
+    private long receiveTaskTime;//使用UsageStatsManager来计算应用使用时长时的开始计算时间
+    public void resetReceiveTaskTime(){//点击领取应用自动审核时,重置这个时间;提交领取奖励时也要重置这个时间
+        receiveTaskTime = System.currentTimeMillis();
+    }
 
+    public long getReceiveTaskTime() {
+        return receiveTaskTime;
+    }
 }

+ 260 - 0
app/src/main/java/com/sheep/gamegroup/usage/AppUsageManager.java

@@ -0,0 +1,260 @@
+package com.sheep.gamegroup.usage;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.Service;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.provider.Settings;
+import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.jaredrummler.android.processes.AndroidProcesses;
+import com.jaredrummler.android.processes.models.AndroidAppProcess;
+import com.sheep.gamegroup.model.entity.AppRecord;
+import com.sheep.gamegroup.model.entity.AppUsage;
+import com.sheep.gamegroup.model.entity.DialogConfig;
+import com.sheep.gamegroup.model.util.AutoTaskListUtil;
+import com.sheep.gamegroup.util.ActivityManager;
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.util.MyDbManager;
+import com.sheep.gamegroup.util.ViewUtil;
+import com.sheep.jiuyan.samllsheep.SheepApp;
+import com.sheep.jiuyan.samllsheep.utils.G;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.TreeMap;
+
+/**
+ * Created by realicing on 2018/6/27.
+ * realicing@sina.com
+ */
+public class AppUsageManager {
+
+    private static AppUsageManager instance = new AppUsageManager();
+
+    private AppUsageManager(){
+    }
+    public static AppUsageManager getInstance(){
+        if (instance == null){
+            instance = new AppUsageManager();
+        }
+        return instance;
+    }
+
+    //记录前台app运行时长
+    public void recordCurrentAppUsage() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//android 7.0以上不支持
+            return;
+        }
+        List<AndroidAppProcess> processes = AndroidProcesses.getRunningForegroundApps(SheepApp.getInstance());
+        AndroidAppProcess androidAppProcess = ListUtil.getLast(processes);
+        if (androidAppProcess != null) {
+            String packageName = androidAppProcess.name;
+            String appName = null;
+            try {
+                PackageInfo packageInfo = androidAppProcess.getPackageInfo(SheepApp.getInstance(), 0);
+                appName = packageInfo.applicationInfo.loadLabel(SheepApp.getInstance().getPackageManager()).toString();
+
+                LogUtil.println("getAppTime", appName, packageName);
+            } catch (PackageManager.NameNotFoundException e) {
+                e.printStackTrace();
+            }
+
+            if(AutoTaskListUtil.getInstance().isLastAppRecord(packageName)){//仍然是之前的app
+                return;
+            }
+
+            long curTime = System.currentTimeMillis();
+            AppRecord appRecord = new AppRecord();
+            appRecord.setPackageName(packageName);
+            if (appName != null)
+                appRecord.setTag(appName);
+
+            AppRecord lastAppRecord = AutoTaskListUtil.getInstance().getLastAppRecord();
+            long lastTime = AutoTaskListUtil.getInstance().getLastTime();
+            if (lastAppRecord != null && lastTime != 0)
+                lastAppRecord.setTime(lastAppRecord.getTime() + curTime - lastTime);
+            if (lastAppRecord != null && AutoTaskListUtil.getInstance().hasTask(lastAppRecord)) {
+                MyDbManager.getInstance().saveOrUpdate(lastAppRecord);
+                LogUtil.println("AppUsageManager", "recordCurrentAppUsage", "MyDbManager", "saveOrUpdate", "lastAppRecord", lastAppRecord.getPackageName(), lastAppRecord.getTime());
+            }
+
+            AutoTaskListUtil.getInstance().setLastTime(curTime);
+            AutoTaskListUtil.getInstance().setLastAppRecord(appRecord);
+        }
+    }
+
+    /**
+     * 需要开启查看应用使用情况的权限
+     *
+     * @return
+     */
+    @SuppressLint("NewApi")
+    public  boolean needOpenLookAppUsageStatsPermisson(boolean isSaveData){
+        if(android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){   // 如果大于等于5.1 再做判断
+            long time = System.currentTimeMillis();
+            UsageStatsManager usageStatsManager=(UsageStatsManager)SheepApp.getInstance().getSystemService(Service.USAGE_STATS_SERVICE);
+            List<UsageStats> queryUsageStats = usageStatsManager != null ? usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, 0, time) : null;
+            boolean isEmpty = ListUtil.isEmpty(queryUsageStats);
+            if(!isEmpty && isSaveData){
+                List<AppUsage> appUsageList = ListUtil.emptyList();
+                for (UsageStats queryUsageStat : queryUsageStats) {
+                    AppUsage appUsage = new AppUsage();
+                    appUsage.setPackageName(queryUsageStat.getPackageName());
+                    appUsage.setTotalTimeInForeground(queryUsageStat.getTotalTimeInForeground());
+                    appUsage.setFirstTimeStamp(queryUsageStat.getFirstTimeStamp());
+                    appUsage.setLastTimeStamp(queryUsageStat.getLastTimeStamp());
+                    appUsageList.add(appUsage);
+                }
+                MyDbManager.getInstance().saveOrUpdate(appUsageList);
+            }
+            return isEmpty;
+        } else{
+            return false;
+        }
+    }
+
+    public void tryOpenLookAppUsageStatsPermisson(boolean isSaveData) {
+            if (!needOpenLookAppUsageStatsPermisson(isSaveData)) {//不需要开启
+                return;
+            }
+            if(AutoTaskListUtil.getInstance().isShowing()){//对话框仍在显示,就不显示 打开权限功能的对话框
+                return;
+            }
+            LogUtil.println("tryOpenLookAppUsageStatsPermisson", "start");
+            AutoTaskListUtil.getInstance().clearAlertDialog();
+            if(!AutoTaskListUtil.getInstance().isEmpty()){
+                LogUtil.println("tryOpenLookAppUsageStatsPermisson", "notEmpty");
+                showAccessibilityDialog();
+            } else {
+                LogUtil.println("tryOpenLookAppUsageStatsPermisson","else");
+            }
+            LogUtil.println("tryOpenLookAppUsageStatsPermisson","end");
+    }
+    public void showAccessibilityDialog() {
+        AlertDialog tipToOpernAccessibilityDialog = ViewUtil.showMsgDialog(SheepApp.getInstance(), new DialogConfig().setTitle("温馨提示!")
+                .setMsg("亲!系统检测到您需要手动开启小绵羊查看应用情况的权限才能继续任务!")
+                .setBtnLeftText("去开启").setBtnLeftOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View view) {
+                        openLookAppUsageStatsPermisson();
+                    }
+                }));
+        tipToOpernAccessibilityDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+            @Override
+            public void onDismiss(DialogInterface dialogInterface) {
+                AutoTaskListUtil.getInstance().clearAlertDialog();
+            }
+        });
+        AutoTaskListUtil.getInstance().setTipToOpernAccessibilityDialog(tipToOpernAccessibilityDialog);
+    }
+    public void openLookAppUsageStatsPermisson(){
+        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
+            try {
+                Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                ActivityManager.getInstance().currentActivity().startActivity(intent);
+            } catch (Exception e) {
+                G.showToast("请自行开启允许查看使用情况的应用界面");
+                e.printStackTrace();
+            }
+        }
+    }
+    private HashMap<String, Long> totalTimeMap = new HashMap<>();
+    private HashMap<String, Long> timeMap = new HashMap<>();
+    public long getTotalTimeInForeground(String packageName) {
+        AppUsage appUsage = new AppUsage();
+        appUsage.setPackageName(packageName);
+        return getTotalTimeInForeground(appUsage);
+    }
+    @SuppressLint("NewApi")
+    public long getTotalTimeInForeground(AppUsage appUsage) {
+        String packageName = appUsage.getPackageName();
+        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
+            UsageStatsManager mUsageStatsManager = (UsageStatsManager) SheepApp.getInstance().getSystemService(Context.USAGE_STATS_SERVICE);//usagestats
+            long time = System.currentTimeMillis();
+            if(mUsageStatsManager != null) {
+                List<UsageStats> usageStatsList = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, AutoTaskListUtil.getInstance().getReceiveTaskTime(), time);
+
+                if (usageStatsList != null && !usageStatsList.isEmpty()) {
+                    if(packageName == null){//为空时需要获取前台的packageName
+                        TreeMap<Long,UsageStats> mySortedMap = new TreeMap<>();
+                        for (UsageStats item : usageStatsList) {
+                            mySortedMap.put(item.getLastTimeUsed(),item);
+                        }
+
+                        UsageStats usageStats = mySortedMap.get(mySortedMap.lastKey());
+
+                        packageName = usageStats.getPackageName();
+                        appUsage.setPackageName(packageName);
+                        long totalTime = usageStats.getTotalTimeInForeground();
+                        long saveTotalTime = MyDbManager.getInstance().getAppUsageTime(packageName);
+                        if (totalTimeMap.containsKey(packageName) && totalTimeMap.get(packageName) == totalTime) {
+                            totalTime += time - timeMap.get(packageName);
+                        } else {
+                            totalTimeMap.put(packageName, totalTime);
+                            timeMap.put(packageName, time);
+                        }
+                        return Math.max(0, totalTime - saveTotalTime);
+                    } else {//小绵羊在前台时调用
+                        for (UsageStats usageStats : usageStatsList) {
+                            if (usageStats != null && TextUtils.equals(packageName, usageStats.getPackageName())) {
+                                return usageStats.getTotalTimeInForeground();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(packageName == null) {//为空时需要获取前台的packageName
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//android 7.0以上不支持
+                return 0;
+            }
+            List<AndroidAppProcess> processes = AndroidProcesses.getRunningForegroundApps(SheepApp.getInstance());
+            AndroidAppProcess androidAppProcess = ListUtil.getLast(processes);
+            if (androidAppProcess != null) {
+                packageName = androidAppProcess.name;
+                appUsage.setPackageName(packageName);
+            }
+            if(TextUtils.isEmpty(packageName)){//没有获取到当前正在运行的应用
+                return 0;
+            }
+        }
+        long runTime = MyDbManager.getInstance().getAppRunTime(packageName);
+
+        if(AutoTaskListUtil.getInstance().isLastAppRecord(packageName)){
+            runTime +=  System.currentTimeMillis() - AutoTaskListUtil.getInstance().getLastTime();
+            AutoTaskListUtil.getInstance().setLastTime(System.currentTimeMillis());
+        }
+        return runTime;
+    }
+
+    public void println() {
+        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
+            UsageStatsManager mUsageStatsManager = (UsageStatsManager) SheepApp.getInstance().getSystemService(Context.USAGE_STATS_SERVICE);//usagestats
+            long time = System.currentTimeMillis();
+            if(mUsageStatsManager != null) {
+                List<UsageStats> usageStatsList = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, AutoTaskListUtil.getInstance().getReceiveTaskTime(), time);
+
+                if (usageStatsList != null && !usageStatsList.isEmpty()) {
+                    for (UsageStats usageStats : usageStatsList) {
+                        if (usageStats != null ) {
+                            LogUtil.println("AppUsageManager", usageStats.getPackageName());
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 10 - 8
app/src/main/java/com/sheep/gamegroup/util/AppUtil.java

@@ -96,20 +96,22 @@ public class AppUtil {
         return (WindowManager)paramContext.getSystemService(Context.WINDOW_SERVICE);
     }
 
-    public static boolean isMainPross(Context context) {
-        return TextUtils.equals(context.getPackageName(), getCurProssName(context));
+    public static boolean isMainProcess(Context context) {
+        return TextUtils.equals(context.getPackageName(), getCurProcessName(context));
     }
 
 
-    public static String getCurProssName(Context context){
+    public static String getCurProcessName(Context context){
         int pid = android.os.Process.myPid();
         String processName = "";
         android.app.ActivityManager manager = (android.app.ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
-        for (ActivityManager.RunningAppProcessInfo process: manager.getRunningAppProcesses()) {
-            if(process.pid == pid)
-            {
-                processName = process.processName;
-                return processName;
+        if(manager != null) {
+            for (ActivityManager.RunningAppProcessInfo process : manager.getRunningAppProcesses()) {
+                LogUtil.println("getRunningAppProcesses",process.processName);
+                if (process.pid == pid) {
+                    processName = process.processName;
+                    return processName;
+                }
             }
         }
         return processName;

+ 3 - 1
app/src/main/java/com/sheep/gamegroup/util/CommonUtil.java

@@ -42,6 +42,7 @@ import com.sheep.gamegroup.model.entity.WithdrawalEty;
 import com.sheep.gamegroup.model.util.AutoTaskListUtil;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.presenter.TryMakeMoneyPresenter;
+import com.sheep.gamegroup.usage.AppUsageManager;
 import com.sheep.gamegroup.view.activity.GameTaskOrderListAct;
 import com.sheep.gamegroup.view.activity.RechargeAct;
 import com.sheep.jiuyan.samllsheep.R;
@@ -491,7 +492,8 @@ public class CommonUtil {
      */
     public void setTAskEnty(TaskEty tAskEnty){
         if(AutoTaskListUtil.getInstance().addTask(tAskEnty)){
-            Jump2View.getInstance().startAccessibility();
+            AutoTaskListUtil.getInstance().resetReceiveTaskTime();
+            AppUsageManager.getInstance().tryOpenLookAppUsageStatsPermisson(true);
         } else {
             AutoTaskListUtil.getInstance().initTaskList();
         }

+ 4 - 0
app/src/main/java/com/sheep/gamegroup/util/ListUtil.java

@@ -21,6 +21,10 @@ public class ListUtil {
     public static <T> T getIndex(List<T> list, int index) {
         return hasIndex(list, index) ? list.get(index) : null;
     }
+    public static <T> T getLast(List<T> list) {
+        int size = ListUtil.size(list);
+        return size > 0 ? list.get(-1 + size) : null;
+    }
 
 
     public static int getTotalPage(int count, int per_page) {

+ 15 - 0
app/src/main/java/com/sheep/gamegroup/util/MyDbManager.java

@@ -4,6 +4,7 @@ import android.database.Cursor;
 import android.os.Handler;
 
 import com.sheep.gamegroup.model.entity.AppRecord;
+import com.sheep.gamegroup.model.entity.AppUsage;
 import com.sheep.gamegroup.model.entity.LoginUser;
 import com.sheep.gamegroup.model.entity.NewbieTaskRecord;
 import com.sheep.gamegroup.model.entity.UserEntity;
@@ -202,4 +203,18 @@ public class MyDbManager {
         }
         return ListUtil.emptyList();
     }
+    public long getAppUsageTime(String packageName){
+        AppUsage appUsage = getAppUsage(packageName);
+        return appUsage == null ? 0 : appUsage.getTotalTimeInForeground();
+    }
+    public AppUsage getAppUsage(String packageName){
+        try{
+            return db.selector(AppUsage.class)
+                    .where("package_name", "=", packageName)
+                    .findFirst();
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
 }

+ 6 - 38
app/src/main/java/com/sheep/gamegroup/util/SysAppUtil.java

@@ -1,7 +1,10 @@
 package com.sheep.gamegroup.util;
 
 import android.app.Activity;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -10,6 +13,7 @@ import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.provider.AlarmClock;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.view.View;
@@ -42,6 +46,8 @@ import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
 import java.util.Locale;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
 import okhttp3.Call;
 import rx.Observable;
@@ -346,44 +352,6 @@ public class SysAppUtil {
         }
         return null;
     }
-    public static void getAppUsageStats(ComponentName aName) {
-        try {
-
-            //获得ServiceManager类
-            Class<?> ServiceManager = Class
-                    .forName("android.os.ServiceManager");
-
-            //获得ServiceManager的getService方法
-            Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
-
-            //调用getService获取RemoteService
-            Object oRemoteService = getService.invoke(null, "usagestats");
-
-            //获得IUsageStats.Stub类
-            Class<?> cStub = Class
-                    .forName("com.android.internal.app.IUsageStats$Stub");
-            //获得asInterface方法
-            Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
-            //调用asInterface方法获取IUsageStats对象
-            Object oIUsageStats = asInterface.invoke(null, oRemoteService);
-            //获得getPkgUsageStats(ComponentName)方法
-            Method getPkgUsageStats = oIUsageStats.getClass().getMethod("getPkgUsageStats", ComponentName.class);
-            //调用getPkgUsageStats 获取PkgUsageStats对象
-            Object aStats = getPkgUsageStats.invoke(oIUsageStats, aName);
-
-            //获得PkgUsageStats类
-            Class<?> PkgUsageStats = Class.forName("com.android.internal.os.PkgUsageStats");
-
-            int aLaunchCount = PkgUsageStats.getDeclaredField("launchCount").getInt(aStats);
-            long aUseTime = PkgUsageStats.getDeclaredField("usageTime").getLong(aStats);
-
-            LogUtil.println("getAppUsageStats", aLaunchCount, aUseTime);
-
-        } catch (Exception e) {
-            LogUtil.println("getAppUsageStats", "Exception", e.toString(), e);
-        }
-
-    }
 
 
 

Datei-Diff unterdrückt, da er zu groß ist
+ 6 - 2
app/src/main/java/com/sheep/gamegroup/util/TestUtil.java


+ 2 - 0
app/src/main/java/com/sheep/gamegroup/view/activity/ActInstallApkList.java

@@ -10,6 +10,7 @@ import com.arialyy.aria.util.CommonUtil;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.model.entity.AppInfo;
 import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.util.StringUtils;
 import com.sheep.gamegroup.util.SysAppUtil;
 import com.sheep.gamegroup.util.ViewHolder;
 import com.sheep.gamegroup.util.ViewUtil;
@@ -105,6 +106,7 @@ public class ActInstallApkList extends BaseActivity {
     }
 
     private void onClickItem(View view, final AppInfo appInfo) {
+        StringUtils.CopyText(this, appInfo.getPackageName());
         readApp(appInfo);
     }
 

+ 4 - 7
app/src/main/java/com/sheep/gamegroup/view/activity/TaskDetailAct.java

@@ -49,6 +49,7 @@ import com.sheep.gamegroup.model.util.EntityUtils;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.presenter.TaskDetailContract;
 import com.sheep.gamegroup.presenter.TaskDetailPresenter;
+import com.sheep.gamegroup.usage.AppUsageManager;
 import com.sheep.gamegroup.util.CommonUtil;
 import com.sheep.gamegroup.util.DeviceUtil;
 import com.sheep.gamegroup.util.Jump2View;
@@ -616,19 +617,15 @@ public class TaskDetailAct extends AbsChooseImageActivity implements TaskDetailC
             String gps = LocationUtils.getInstance().getLongitudeLatitude(getApplicationContext());
             JSONObject object = new JSONObject();
             object.put("gps", gps);
-            long runTime = MyDbManager.getInstance().getAppRunTime(taskEty.getPackage_names());
-
-            AppRecord lastAppRecord = AutoTaskListUtil.getInstance().getLastAppRecord();
-            if(lastAppRecord != null && TextUtils.equals(taskEty.getPackage_names(), lastAppRecord.getPackageName())){
-                runTime +=  System.currentTimeMillis() - AutoTaskListUtil.getInstance().getLastTime();
-                AutoTaskListUtil.getInstance().setLastTime(System.currentTimeMillis());
-            }
+            long runTime = AppUsageManager.getInstance().getTotalTimeInForeground(taskEty.getPackage_names());
             if(runTime <= 0){//时间小于等于0则不提交
                 G.showToast("该任务时长未达到,请继续去体验应用哦!");
                 return;
             }
 
             MyDbManager.getInstance().removeAppRecord();
+            AutoTaskListUtil.getInstance().resetReceiveTaskTime();
+            
             LogUtil.println("MonitorAppService runTime = "+runTime);
             object.put("task_time", runTime/1000);
             object.put("release_task_id", taskReleaseEty.getId());

+ 0 - 39
app/src/main/java/com/sheep/jiuyan/samllsheep/BaseApplication.java

@@ -4,7 +4,6 @@ package com.sheep.jiuyan.samllsheep;
 import android.app.Instrumentation;
 
 import com.kfzs.duanduan.KFZSApp;
-import com.sheep.gamegroup.hook.InstrumentationProxy;
 import com.sheep.gamegroup.util.LogUtil;
 import com.umeng.commonsdk.UMConfigure;
 import com.umeng.socialize.PlatformConfig;
@@ -40,44 +39,6 @@ public abstract class BaseApplication extends KFZSApp {
         JPushInterface.setDebugMode(BuildConfig.DEBUG);
         JPushInterface.init(this);
 
-
-        try {
-            //这个方法一般是写在Application的oncreate函数里面,如果你写在activity里面的oncrate函数里面就已经晚了
-            attachContext();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
     }
 
-
-
-
-    public static final String TAG = "BaseApplication";
-    public static final String ACTIVIT_THREAD = "android.app.ActivityThread";
-    public static final String CURRENT_ACTIVITY_THREAD = "currentActivityThread";
-    public static final String INSTRUMENTATION = "mInstrumentation";
-    public static void attachContext() throws Exception{
-
-        //获取当前的ActivityThread对象
-        Class<?> activityThreadClass = Class.forName(ACTIVIT_THREAD);
-        Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod(CURRENT_ACTIVITY_THREAD);
-        currentActivityThreadMethod.setAccessible(true);
-        Object currentActivityThread = currentActivityThreadMethod.invoke(null);
-
-
-        //拿到在ActivityThread类里面的原始mInstrumentation对象
-        Field mInstrumentationField = activityThreadClass.getDeclaredField(INSTRUMENTATION);
-        mInstrumentationField.setAccessible(true);
-        Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);
-
-
-        //构建我们的代理对象
-        Instrumentation evilInstrumentation = new InstrumentationProxy(mInstrumentation);
-
-        //通过反射,换掉字段,注意,这里是反射的代码,不是Instrumentation里面的方法
-        mInstrumentationField.set(currentActivityThread, evilInstrumentation);
-
-        //做个标记,方便后面查看
-        LogUtil.println(TAG, "has go in BaseApplication attachContext method");
-    }
 }

+ 1 - 2
app/src/main/java/com/sheep/jiuyan/samllsheep/SheepApp.java

@@ -83,7 +83,7 @@ public class SheepApp extends BaseApplication {
     @Override
     public void onCreate() {
         super.onCreate();
-        if(AppUtil.isMainPross(this)) {
+        if(AppUtil.isMainProcess(this)) {
             mContext = getApplicationContext();
             mSheepApp = this;
             connectAddress = ConnectAddress.sheep.getDefultConnectAddress();
@@ -147,7 +147,6 @@ public class SheepApp extends BaseApplication {
                 if(!notStop) {
                     notStop = true;
                     LogUtil.println("SheepApp SHEEP_RESUME");
-                    AutoTaskListUtil.getInstance().initTaskList();
                     UMConfigUtils.Event.SHEEP_RESUME.onEvent();
                 }
                 Jump2View.getInstance().startFloat(activity, false);

+ 232 - 106
app/src/main/java/com/sheep/jiuyan/samllsheep/service/FloatService.java

@@ -2,26 +2,45 @@ package com.sheep.jiuyan.samllsheep.service;
 
 import android.app.Service;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.PixelFormat;
 import android.os.Build;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.support.v7.app.AlertDialog;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
+import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
+import com.sheep.gamegroup.model.entity.AppUsage;
+import com.sheep.gamegroup.model.entity.DialogConfig;
+import com.sheep.gamegroup.model.util.AutoTaskListUtil;
+import com.sheep.gamegroup.usage.AppUsageManager;
 import com.sheep.gamegroup.util.Jump2View;
 import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.util.TestUtil;
+import com.sheep.gamegroup.util.TimeUtil;
+import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.DeviceInfo;
+import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.SpUtils;
 
+import java.util.HashMap;
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 import rx.Observable;
@@ -35,147 +54,102 @@ import rx.schedulers.Schedulers;
  * realicing@sina.com
  */
 public class FloatService extends Service {
-
-    private static final String TAG = "MainService";
-
-    LinearLayout mFloatwindow;
-    WindowManager.LayoutParams params;
-    WindowManager mWm;
-
-    ImageView floaticon;
-
-    //状态栏高度.
-    int statusBarHeight = -1;
-
-    //不与Activity进行绑定.
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        createToucher();
-        startTimer();
-    }
-
     private void stopTimer() {
-        if(subscription != null){
+        if (subscription != null) {
             subscription.unsubscribe();
         }
         subscription = null;
     }
 
     private Subscription subscription;
+
     private void startTimer() {
-        if(subscription == null)
-            subscription = Observable.interval(60_000L, TimeUnit.MILLISECONDS)
+        if (subscription == null)
+            subscription = Observable.interval(10_000L, TimeUnit.MILLISECONDS)
                     .subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
                     .subscribe(new Action1<Long>() {
                         @Override
                         public void call(Long count) {
-                            LogUtil.println("FloatService","count","=",count);
-                            try {
-                                if(!TextUtils.isEmpty(SpUtils.getOpenId(SheepApp.getInstance()))) {//登录情况下才检查是否有应用自动审核任务,是否开启辅助功能
-                                    Jump2View.getInstance().startAccessibility();
+                            LogUtil.println("FloatService", "count", "=", count);
+                            if (!TextUtils.isEmpty(SpUtils.getOpenId(SheepApp.getInstance())) &&!AutoTaskListUtil.getInstance().isEmpty()) {//登录情况下并且有应用自动审核任务才会记录
+                                if(count % 60 == 0){
+                                    AppUsageManager.getInstance().tryOpenLookAppUsageStatsPermisson(false);
+                                }
+                                try {
+                                    AppUsageManager.getInstance().recordCurrentAppUsage();
+                                } catch (Exception e) {
+                                    e.printStackTrace();
                                 }
-                            } catch (Exception e) {
-                                e.printStackTrace();
+                                Message message = handler.obtainMessage(1);
+                                message.obj = count;
+                                handler.sendMessage(message);
+                            } else {
+                                handler.sendEmptyMessage(2);
                             }
 
                         }
                     }, new Action1<Throwable>() {
                         @Override
                         public void call(Throwable throwable) {
-                            LogUtil.println("FloatService","Throwable","=",throwable.getMessage());
+                            LogUtil.println("FloatService", "Throwable", "=", throwable.getMessage());
                         }
                     });
     }
 
 
-
-    private void createToucher() {
-        //赋值WindowManager&LayoutParam.
-        params = new WindowManager.LayoutParams();
-        if(mWm==null) {
-            mWm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
-        }
-        //设置type.系统提示型窗口,一般都在应用程序窗口之上.
-        //设置效果为背景透明.
-        params.format = PixelFormat.RGBA_8888;
-        //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
-        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-//
-//        //设置窗口初始停靠位置.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            //  大于等于 24 即为 7.0 及以上执行内容
-            Log.e("qx", "7.0");
-            params.type = WindowManager.LayoutParams.TYPE_PHONE; // 7.1
-        } else {
-            //  低于 24 即为 7.0 以下执行内容
-            params.type = WindowManager.LayoutParams.TYPE_TOAST;   // 4.4
-            Log.e("qx", "4.4");
-
-        }
-
-        params.gravity = Gravity.LEFT | Gravity.TOP;
-        params.x = 0;
-        params.y = DeviceInfo.dip2px(getApplicationContext(), 25);
-
-        //设置悬浮窗口长宽数据.
-        params.width = -2;
-        params.height = DeviceInfo.dip2px(getApplicationContext(), 40f);
-
-        LayoutInflater inflater = LayoutInflater.from(getApplication());
-        //获取浮动窗口视图所在布局.
-        mFloatwindow = (LinearLayout) inflater.inflate(R.layout.float_window, null);
-        //添加toucherlayout
-        Log.i(TAG, "toucherlayout-->left:" + mFloatwindow.getLeft());
-        Log.i(TAG, "toucherlayout-->right:" + mFloatwindow.getRight());
-        Log.i(TAG, "toucherlayout-->top:" + mFloatwindow.getTop());
-        Log.i(TAG, "toucherlayout-->bottom:" + mFloatwindow.getBottom());
-
-        //主动计算出当前View的宽高信息.
-        mFloatwindow.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-
-        //用于检测状态栏高度.
-        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
-        if (resourceId > 0) {
-            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
-        }
-        Log.i(TAG, "状态栏高度为:" + statusBarHeight);
-
-        //浮动窗口按钮.
-        floaticon = mFloatwindow.findViewById(R.id.floate_icon);
-        floaticon.setAlpha(0.0f);
-
-
+    //不与Activity进行绑定.
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
     }
 
     @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        try {
-            if (intent != null && intent.getBooleanExtra("isShow", true)) {
-                if (mFloatwindow != null) {
-                    mWm.addView(mFloatwindow, params);
+    public void onCreate() {
+        super.onCreate();
+        createFloatView();
+        startTimer();
+    }
+    private Handler handler = new Handler(Looper.getMainLooper()){
+        @Override
+        public void handleMessage(Message msg) {
+            try {
+                switch (msg.what) {
+                    case 1:
+                        onHandleMessage1();
+                        break;
+                    case 2:
+                        onHandleMessage2();
+                        break;
                 }
-            } else {
-                if (mFloatwindow != null)
-                    mWm.removeViewImmediate(mFloatwindow);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
 
+        private void onHandleMessage1() {
+            AppUsage appUsage = new AppUsage();
+            //更新悬浮窗
+            long totalTimeInForeground = AppUsageManager.getInstance().getTotalTimeInForeground(appUsage);
+            if(!AutoTaskListUtil.getInstance().hasTask(appUsage.getPackageName())){
+                onHandleMessage2();
+                return;
             }
-        } catch (Exception ignore) {
+            btn_floatView.setText(String.format(Locale.CHINA,"约运行%s",TimeUtil.getHours(totalTimeInForeground)));
+            floatView.setAlpha(1.0f);
+            wm.updateViewLayout(floatView, params);
         }
-        return super.onStartCommand(intent, flags, START_STICKY);
-    }
+
+        private void onHandleMessage2() {
+            floatView.setAlpha(0.0f);
+            wm.updateViewLayout(floatView, params);
+        }
+    };
     @Override
     public void onDestroy() {
-        if (floaticon != null) {
+        if (floatView != null) {
             try {
-                mWm.removeViewImmediate(mFloatwindow);
+                wm.removeViewImmediate(floatView);
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -184,4 +158,156 @@ public class FloatService extends Service {
         super.onDestroy();
     }
 
+//    public static final String OPERATION = "operation";
+    public static final int OPERATION_SHOW = 100;
+    public static final int OPERATION_HIDE = 101;
+
+    private static final int HANDLE_CHECK_ACTIVITY = 200;
+
+    private boolean isAdded = false; // 是否已增加悬浮窗
+    private static WindowManager wm;
+    private static WindowManager.LayoutParams params;
+    private View floatView;
+    private TextView btn_floatView;
+
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+//        int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);
+        if(intent != null) {
+            int operation = intent.getBooleanExtra("isShow", true) ? OPERATION_SHOW : OPERATION_HIDE;
+            mHandler.sendEmptyMessage(operation);
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    private Handler mHandler = new TwHandler(this);
+
+    static class TwHandler extends Handler {
+        TwHandler(FloatService service) {
+            this.service = service;
+        }
+
+        FloatService service;
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case OPERATION_SHOW:
+                    if (!service.isAdded) {
+                        try {
+                            service.floatView.setAlpha(1.0f);
+                            wm.updateViewLayout(service.floatView, params);
+//                            wm.addView(service.floatView, params);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        service.isAdded = true;
+                    }
+                    break;
+                case OPERATION_HIDE:
+                case HANDLE_CHECK_ACTIVITY:
+                    if (service.isAdded) {
+                        try {
+                            service.floatView.setAlpha(0.0f);
+                            wm.updateViewLayout(service.floatView, params);
+//                            wm.removeViewImmediate(service.floatView);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        service.isAdded = false;
+                    }
+                    break;
+            }
+        }
+    }
+    private boolean canTouchWindow = false;//是否可以操作悬浮窗
+
+    public void setCanTouchWindow(boolean canTouchWindow) {
+        this.canTouchWindow = canTouchWindow;
+    }
+
+    /**
+     * 创建悬浮窗
+     */
+    private void createFloatView() {
+        LayoutInflater inflater = LayoutInflater.from(getApplication());
+//        //获取浮动窗口视图所在布局.
+        floatView = inflater.inflate(R.layout.float_window, null);
+        btn_floatView = floatView.findViewById(R.id.float_tv);
+
+        wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
+        params = new WindowManager.LayoutParams();
+
+        // 设置window type
+        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+        /*
+         * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 那么优先级会降低一些,
+         * 即拉下通知栏不可见
+         */
+
+        params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
+
+        if(canTouchWindow) {
+            // 设置Window flag
+            params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            // 设置悬浮窗的Touch监听
+            floatView.setOnTouchListener(new View.OnTouchListener() {
+                int lastX, lastY;
+                int paramX, paramY;
+                private boolean isMove = false;
+                private long downTime = 0;
+
+                public boolean onTouch(View v, MotionEvent event) {
+                    switch (event.getAction()) {
+                        case MotionEvent.ACTION_DOWN:
+                            isMove = false;
+                            downTime = System.currentTimeMillis();
+                            lastX = (int) event.getRawX();
+                            lastY = (int) event.getRawY();
+                            paramX = params.x;
+                            paramY = params.y;
+                            break;
+                        case MotionEvent.ACTION_MOVE:
+                            int dx = (int) event.getRawX() - lastX;
+                            int dy = (int) event.getRawY() - lastY;
+                            params.x = paramX + dx;
+                            params.y = paramY + dy;
+                            // 更新悬浮窗位置
+                            wm.updateViewLayout(floatView, params);
+                            isMove = true;
+                            break;
+                        case MotionEvent.ACTION_UP:
+                            if(!isMove && System.currentTimeMillis()-downTime < 1000L){//没有移动过并且小于1秒就弹起来就点击
+                                v.performClick();
+                            }
+                            isMove = false;
+                            break;
+                    }
+                    return false;
+                }
+            });
+            floatView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    //TODO 设置点击悬浮窗的响应
+                }
+            });
+        } else {
+            /*
+             * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
+             */
+            params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+        }
+
+        // 设置悬浮窗的长得宽
+        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
+        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+        params.gravity = Gravity.START | Gravity.BOTTOM;
+
+        floatView.setAlpha(0.0f);
+        wm.addView(floatView, params);
+        isAdded = true;
+    }
 }

+ 11 - 6
app/src/main/res/layout/float_window.xml

@@ -1,14 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/float_ll"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:background="@color/float_bg"
     android:orientation="horizontal">
 
-    <ImageView
-        android:id="@+id/floate_icon"
-        android:layout_width="40dp"
-        android:layout_height="40dp"
-        android:scaleType="fitCenter"
-        android:src="@drawable/icon"/>
+    <TextView
+        android:id="@+id/float_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dp"
+        android:textSize="12sp"
+        android:textColor="@color/black_deep"
+        android:gravity="center"
+        android:text="没有正在运行的任务"/>
 
 </LinearLayout>

+ 1 - 0
app/src/main/res/values/gamegroup_color.xml

@@ -43,4 +43,5 @@
     <color name="green_60BE5E">#60BE5E</color>
     <color name="blue_91BDD6">#91BDD6</color>
 
+    <color name="float_bg">#33F9F9F9</color>
 </resources>

+ 2 - 2
gradle.properties

@@ -17,8 +17,8 @@
 # org.gradle.parallel=true
 #android.injected.build.model.only.versioned = 3
 
-VERSION_NAME=2.6.1
-VERSION_CODE=2006001
+VERSION_NAME=2.7.0
+VERSION_CODE=2007000
 ANDROID_COMPILE_SDK_VERSION=27
 ANDROID_BUILD_TOOLS_VERSION=27.0.2
 ANDROID_MIN_SDK_VERSION=18