Explorar o código

打卡界面倒计时与打卡状态分离;
尝试将监听截图放到单独的后台进程

zengjiebin %!s(int64=7) %!d(string=hai) anos
pai
achega
5761f7a4d1

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

@@ -120,13 +120,14 @@
 
         <service android:name=".service.DownloadService" />
         <service
-            android:name=".service.FloatService"
-            android:enabled="true"
-            android:exported="true" />
+            android:name=".service.FloatService"/>
         <service
-            android:name=".service.FloatShotScreenService"
-            android:enabled="true"
-            android:exported="true" />
+            android:name=".service.FloatShotScreenService" />
+        <service
+            android:name=".service.ListenerShotService"
+            android:priority="1000"
+            android:exported="false"
+            android:process=":listener" />
 
         <provider
             android:name=".provider.SheepFileProvider"
@@ -642,7 +643,7 @@
             android:screenOrientation="portrait" />
         <activity
             android:name="com.sheep.gamegroup.view.activity.MessageInteractionDetailActivity"
-            android:exported="true" />
+            android:screenOrientation="portrait" />
         <activity
             android:name="com.sheep.gamegroup.view.activity.ActModifyThird"
             android:screenOrientation="portrait" />
@@ -654,7 +655,7 @@
             android:screenOrientation="portrait" />
         <activity
             android:name="com.sheep.gamegroup.view.activity.ActSysNfDetail"
-            android:exported="true" />
+            android:screenOrientation="portrait" />
         <activity
             android:name="com.sheep.gamegroup.view.activity.InvitationActivity"
             android:screenOrientation="portrait" />

+ 15 - 5
app/src/main/java/com/sheep/gamegroup/absBase/BaseActivity.java

@@ -17,18 +17,28 @@ import butterknife.Unbinder;
 public abstract class BaseActivity extends AppCompatActivity {
 
     protected DialogLoading dialogLoading;
-    public Unbinder bind;
+    public Unbinder unbinder;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(getLayoutId());
-        bind = ButterKnife.bind(this);
+        unbinder = ButterKnife.bind(this);
         initView();
         initListener();
         initData();
     }
-
+    public void reBindView(){
+        if(unbinder != null){
+            try {
+                unbinder.unbind();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            unbinder = null;
+        }
+        unbinder = ButterKnife.bind(this);
+    }
     public boolean isShowing() {
         return dialogLoading != null && dialogLoading.getAlertDialog() != null && dialogLoading.getAlertDialog().isShowing();
     }
@@ -82,8 +92,8 @@ public abstract class BaseActivity extends AppCompatActivity {
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        if (this.bind != null) {
-            this.bind.unbind();
+        if (this.unbinder != null) {
+            this.unbinder.unbind();
         }
     }
 }

+ 4 - 82
app/src/main/java/com/sheep/gamegroup/util/DataUtil.java

@@ -1,13 +1,9 @@
 package com.sheep.gamegroup.util;
 
-import android.annotation.SuppressLint;
 import android.app.Activity;
-import android.app.usage.UsageStats;
-import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.Intent;
 import android.media.projection.MediaProjectionManager;
-import android.os.Build;
 import android.os.Bundle;
 import android.text.TextUtils;
 
@@ -17,7 +13,6 @@ import com.sheep.gamegroup.model.api.BaseMessageConverter;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.ScreenShotConfig;
 import com.sheep.gamegroup.model.entity.UserEntity;
-import com.sheep.gamegroup.model.util.AutoTaskListUtil;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.jiuyan.samllsheep.BuildConfig;
 import com.sheep.jiuyan.samllsheep.SheepApp;
@@ -30,15 +25,11 @@ import org.afinal.simplecache.ACache;
 import org.afinal.simplecache.ApiKey;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
-import java.util.concurrent.TimeUnit;
 
-import rx.Observable;
 import rx.android.schedulers.AndroidSchedulers;
 import rx.functions.Action1;
 import rx.schedulers.Schedulers;
@@ -323,7 +314,7 @@ public class DataUtil {
      *
      * @return
      */
-    public File getScreenShotsFile(String packageName) {
+    public static File getScreenShotsFile(String packageName) {
         File dir = getScreenShotsDir(packageName);
         return new File(dir, TimeUtil.getDate("yyyy-MM-dd-hh-mm-ss")+".png");
     }
@@ -333,7 +324,7 @@ public class DataUtil {
      *
      * @return
      */
-    public File getScreenShotsDir() {
+    public static File getScreenShotsDir() {
         return SheepApp.getInstance().getDir("ScreenShots", Context.MODE_PRIVATE);
     }
     /**
@@ -341,7 +332,7 @@ public class DataUtil {
      *
      * @return
      */
-    public File getScreenShotsDir(String packageName) {
+    public static File getScreenShotsDir(String packageName) {
         File dir = new File(getScreenShotsDir(), packageName);
         if(!dir.exists())
             dir.mkdirs();
@@ -353,7 +344,7 @@ public class DataUtil {
      *
      * @return
      */
-    public ArrayList<String> getAllScreenShotList() {
+    public static ArrayList<String> getAllScreenShotList() {
         File[] dirs = getScreenShotsDir().listFiles();
         ArrayList<String> list = ListUtil.emptyList();
         if(dirs != null) {
@@ -421,75 +412,6 @@ public class DataUtil {
 
     }
 
-    /**
-     * 获取前台运行的程序的包名
-     * @return
-     */
-    @SuppressLint("NewApi")
-    public static String getPackageNameInForeground() {
-        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 (!ListUtil.isEmpty(usageStatsList)) {
-                    TreeMap<Long, UsageStats> mySortedMap = new TreeMap<>();
-                    for (UsageStats item : usageStatsList) {
-                        mySortedMap.put(item.getLastTimeUsed(), item);
-                    }
-
-                    UsageStats usageStats = mySortedMap.get(mySortedMap.lastKey());
-
-                    return usageStats.getPackageName();
-                }
-            }
-        }
-        android.app.ActivityManager.RunningAppProcessInfo process = getAppProcessInfoInForeground();
-        if (process != null) {
-            return process.processName;
-        }
-        return null;
-    }
-
-    private static android.app.ActivityManager.RunningAppProcessInfo getAppProcessInfoInForeground() {
-        android.app.ActivityManager manager = (android.app.ActivityManager) SheepApp.getInstance().getSystemService(Context.ACTIVITY_SERVICE);
-        List<android.app.ActivityManager.RunningAppProcessInfo> processList = manager == null ? null : manager.getRunningAppProcesses();
-        if (!ListUtil.isEmpty(processList)) {
-            for (android.app.ActivityManager.RunningAppProcessInfo item : processList) {
-                if (item != null && item.importance == android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
-                    return item;
-                }
-            }
-        }
-        return null;
-    }
-
-    public void addPng(final String imagePath) {
-        final String packageName = getPackageNameInForeground();
-        if(TextUtils.isEmpty(packageName)){
-            LogUtil.println("ScreenShotListenManager", "无法获取到当前运行的应用的包名");
-            return;
-        }
-//        File shotFile = getScreenShotsFile(packageName);
-        LogUtil.println("ScreenShotListenManager", packageName);
-        Observable.just(1).delay(1, TimeUnit.SECONDS)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(new Action1<Integer>() {
-                    @Override
-                    public void call(Integer integer) {
-                        try {
-                            FileUtil.copyFileToDir(new File(imagePath), getScreenShotsDir(packageName));
-                        } catch (IOException e) {
-                            e.printStackTrace();
-                            LogUtil.println("ScreenShotListenManager", "复制截屏图片失败");
-                        }
-                    }
-                });
-
-    }
-
     //-----------------------------------------其它数据部分-----------------------------------------------------结束
     //-----------------------------------------引导页中用到的是否为新版部分-----------------------------------------------------开始
     private int versionType = 0;

+ 134 - 0
app/src/main/java/com/sheep/gamegroup/util/RunningTaskUtil.java

@@ -0,0 +1,134 @@
+package com.sheep.gamegroup.util;
+
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.os.Build;
+
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.TreeMap;
+
+/**
+ * Created by realicing on 2018/9/20.
+ * realicing@sina.com
+ */
+public class RunningTaskUtil {
+    private static final String TAG="RunningTaskUtil";
+    public static final int TWENTYSECOND = 1000 * 20;
+    public static final int THIRTYSECOND = 1000 * 60 * 60 * 3;
+    private UsageStatsManager mUsageStatsManager;
+    private Field mLastEventField;
+    private Context context;
+    public RunningTaskUtil(Context context){
+        this.context = context;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){
+            mUsageStatsManager = (UsageStatsManager)context.getApplicationContext().getSystemService(Context.USAGE_STATS_SERVICE);
+        }
+    }
+
+    public String getTopRunningTasks(){
+        //用两次取当前应用的办法来提高正确性
+        return getTopRunningTasks(true);
+    }
+
+    public String getTopRunningTasks(boolean isFirst){
+        String topPackageName =null;
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {
+            long time = System.currentTimeMillis();
+            // We get usage stats for the last 10 seconds
+            List<UsageStats> stats ;
+            if (isFirst){
+                stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - TWENTYSECOND, time);
+            }else {
+                stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - THIRTYSECOND, time);
+            }
+            // Sort the stats by the last time used
+            if(stats != null) {
+                TreeMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
+                for (UsageStats usageStats : stats) {
+                    mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
+                }
+                if(!mySortedMap.isEmpty()) {
+                    NavigableSet<Long> keySet=mySortedMap.navigableKeySet();
+                    Iterator<Long> iterator=keySet.descendingIterator();
+                    while(iterator.hasNext()){
+                        UsageStats usageStats = mySortedMap.get(iterator.next());
+                        if (mLastEventField==null) {
+                            try {
+                                mLastEventField = UsageStats.class.getField("mLastEvent");
+                            } catch (NoSuchFieldException e) {
+                                break;
+                            }
+                        }
+                        if (mLastEventField!=null) {
+                            int lastEvent;
+                            try {
+                                lastEvent = mLastEventField.getInt(usageStats);
+                            } catch (IllegalAccessException e) {
+                                break;
+                            }
+                            if (lastEvent==1){
+                                topPackageName=usageStats.getPackageName();
+                                break;
+                            }
+                        }else {
+                            break;
+                        }
+                    }
+                    if (topPackageName==null){
+                        topPackageName =  mySortedMap.get(mySortedMap.lastKey()).getPackageName();
+                        if ("com.android.systemui".equals(topPackageName)){
+                            Long currentKey = null;
+                            String tempPackage = topPackageName;
+                            currentKey = (Long) ((TreeMap) mySortedMap).floorKey(mySortedMap.lastKey()-1);
+                            if (currentKey!=null) {
+                                tempPackage = mySortedMap.get(currentKey).getPackageName();
+                            }
+                            if (tempPackage!=null){
+                                if (context.getPackageName().equals(tempPackage)){
+                                    currentKey = (Long) ((TreeMap) mySortedMap).floorKey(currentKey-1);
+                                    if (currentKey!=null) {
+                                        tempPackage = mySortedMap.get(currentKey).getPackageName();
+                                    }
+                                }
+                            }
+                            if (tempPackage!=null){
+                                topPackageName=tempPackage;
+                            }
+                        }
+                    }
+                }else {
+                    if (isFirst){
+                        topPackageName = getTopRunningTasks(false);
+                    }
+                }
+            }
+        }
+        return topPackageName;
+    }
+
+    public String getTopRunningTasksOrigin(){
+        String topPackageName =null;
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {
+            long time = System.currentTimeMillis();
+            // We get usage stats for the last 10 seconds
+            List<UsageStats> stats ;
+            stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - TWENTYSECOND, time);
+            // Sort the stats by the last time used
+            if(stats != null) {
+                TreeMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
+                for (UsageStats usageStats : stats) {
+                    mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
+                }
+                if(!mySortedMap.isEmpty()) {
+                    topPackageName =  mySortedMap.get(mySortedMap.lastKey()).getPackageName();
+                }
+            }
+        }
+        return topPackageName;
+    }
+
+}

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

@@ -145,7 +145,7 @@ public class SysAppUtil {
 //            File cacheDir = SheepApp.getInstance().getExternalCacheDir();
 //            long filesDirSize = getFolderSize(filesDir);
 //            long cacheSize = getFolderSize(cacheDir);
-            long screenShotsSize = getFolderSize(DataUtil.getInstance().getScreenShotsDir());
+            long screenShotsSize = getFolderSize(DataUtil.getScreenShotsDir());
             long apkSize = getFolderSize(new File(ClassFileHelper.DIR));
             File cacheDirPath = SheepApp.getInstance().getCacheDir();
             long glideSize = getFolderSize(new File( cacheDirPath, InternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR));

+ 2 - 2
app/src/main/java/com/sheep/gamegroup/util/TestUtil.java

@@ -224,11 +224,11 @@ public class TestUtil {
                                 DialogProgress.showDialog(activity);
                                 break;
                             case "查看截图":
-                                File root = DataUtil.getInstance().getScreenShotsDir();
+                                File root = DataUtil.getScreenShotsDir();
                                 if(!root.exists() || root.listFiles().length <= 0){
                                     G.showToast("暂无截图");
                                 } else {
-                                    File dir = DataUtil.getInstance().getScreenShotsDir().listFiles()[0];
+                                    File dir = DataUtil.getScreenShotsDir().listFiles()[0];
                                     if (dir.exists()) {
                                         G.showToast("截图个数为:" + dir.list().length);
                                     } else {

+ 17 - 28
app/src/main/java/com/sheep/gamegroup/view/activity/ActSignCard.java

@@ -65,6 +65,8 @@ public class ActSignCard extends BaseActivity {
     TextView sign_card_award;
     @BindView(R.id.sign_card_join)
     TextView sign_card_join;
+    @BindView(R.id.sign_card_time)
+    TextView sign_card_time;
     @BindView(R.id.sign_card_title1)
     TextView sign_card_title1;
     @BindView(R.id.sign_card_title2)
@@ -256,7 +258,9 @@ public class ActSignCard extends BaseActivity {
                         ViewUtil.setText(sign_card_award, punchAndSign.getTotal_award());
                         ViewUtil.setText(sign_card_title1, String.format(Locale.CHINA, "%s战况", punchAndSign.getDayText()));
                         ViewUtil.setText(sign_card_title2, String.format(Locale.CHINA, "%s之星", punchAndSign.getDayText()));
-                        initBtnState();
+                        if((totalTime = punchAndSign.getCountdown()) > 0) {//有倒计时
+                            handler.sendEmptyMessage(0);//开始计时
+                        }
                     }
 
                     @Override
@@ -432,10 +436,12 @@ public class ActSignCard extends BaseActivity {
         public void handleMessage(Message msg) {
             switch (msg.what){
                 case 0://UPDATE_TIME:
-                    if(totalTime > 0) {
-                        sign_card_join.setEnabled(false);
-                        sign_card_join.setText(String.format(Locale.CHINA, "%s后可打卡", TimeUtil.getHours(totalTime-- * 1000)));
+                    if(totalTime > 0 && !isCanSignUp) {
+                        sign_card_time.setVisibility(View.VISIBLE);
+                        sign_card_time.setText(String.format(Locale.CHINA, "%s后可打卡", TimeUtil.getHours(totalTime-- * 1000)));
                         sendEmptyMessageDelayed(msg.what, 1000L);
+                    } else {
+                        sign_card_time.setVisibility(View.GONE);
                     }
                     break;
             }
@@ -443,32 +449,15 @@ public class ActSignCard extends BaseActivity {
     };
     private long totalTime = INIT;
     private void initBtnState() {
-        if(punchAndSign != null && initCanSignUp == SUCCESS && punchType > SUCCESS){//初始化成功
-            switch (punchType){
-                case PUNCH_TYPE_NOT_SIGN_UP:
-                    sign_card_join.setEnabled(false);
-                    sign_card_join.setText("昨日未报名");
-                    break;
-                case PUNCH_TYPE_CAN_PUNCH://可以打卡
-                    sign_card_join.setEnabled(true);
-                    sign_card_join.setText("立即打卡");
-                    break;
-                case PUNCH_TYPE_HAD_PUNCH://已打卡
-                    sign_card_join.setEnabled(false);
-                    sign_card_join.setText("已参与");
-                    break;
-            }
-            if (isCanSignUp) {//可以报名
-                sign_card_join.setEnabled(true);
-                sign_card_join.setText("参加打卡挑战");
-            } else if(totalTime > 0) {
-                sign_card_join.setEnabled(false);
-                totalTime = punchAndSign.getCountdown();
-                handler.sendEmptyMessage(0);//开始计时
-            }
+        if (punchType == PUNCH_TYPE_CAN_PUNCH) {//可以打卡
+            sign_card_join.setEnabled(true);
+            sign_card_join.setText("立即打卡");
+        } else if (initCanSignUp == SUCCESS && isCanSignUp) {//可以报名
+            sign_card_join.setEnabled(true);
+            sign_card_join.setText("参加打卡挑战");
         } else {
             sign_card_join.setEnabled(false);
-            sign_card_join.setText(R.string.loading);
+            sign_card_join.setText("已参与");
         }
     }
 

+ 5 - 2
app/src/main/java/com/sheep/gamegroup/view/activity/TaskDetailAct.java

@@ -933,10 +933,10 @@ public class TaskDetailAct extends AbsChooseImageActivity implements TaskDetailC
         }
         if (commitScreenShotTaskId > 0) {
             if ((DataUtil.IS_USE_SCREEN_SHOT || DataUtil.IS_LISTEN_SCREEN_SHOT) && taskEty.needShotScreen()) {//小绵羊截图方案与监听方案
-                File dir = DataUtil.getInstance().getScreenShotsDir(taskEty.getPackage_names());
+                File dir = DataUtil.getScreenShotsDir(taskEty.getPackage_names());
                 showChooseDialog(false, true, DEFAULT_MAX_COUNT, dir);
             } else {//用户手动截图方案
-                ArrayList<String> imageUriList = DataUtil.getInstance().getAllScreenShotList();
+                ArrayList<String> imageUriList = DataUtil.getAllScreenShotList();
 
                 showChooseDialog(false, true, DEFAULT_MAX_COUNT, imageUriList);
             }
@@ -1551,6 +1551,9 @@ public class TaskDetailAct extends AbsChooseImageActivity implements TaskDetailC
         taskReleaseEty = DataUtil.getInstance().getCacheResult(ApiKey.releaseTaskDesc(releaseTaskId), TaskReleaseEty.class);
         hideProgress();
         if (taskReleaseEty != null) {
+            if(empty_view == null){
+                reBindView();
+            }
             empty_view.setVisibility(View.GONE);
             loadData();
         }

+ 8 - 11
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment.java

@@ -108,19 +108,16 @@ public abstract class BaseListFragment<T> extends BaseFragment {
         new Handler().postDelayed(new Runnable() {
             @Override
             public void run() {
-                if(per_page != 100){
-                    if(!loadMore){
-                        loadMore = true;
-                        if(ListUtil.size(list) >= per_page*page){
-                            page += 1;
-                            initData();
-                        }else {
-                            view_list.setNoMore(true);
-                            setNoMore(true);
-                        }
+                if(!loadMore){
+                    loadMore = true;
+                    if(ListUtil.size(list) >= per_page*page){
+                        page += 1;
+                        initData();
+                    }else {
+                        view_list.setNoMore(true);
+                        setNoMore(true);
                     }
                 }
-
             }
         },1000);
     }

+ 13 - 19
app/src/main/java/com/sheep/jiuyan/samllsheep/SheepApp.java

@@ -39,6 +39,7 @@ import com.sheep.gamegroup.view.activity.LoginAct;
 import com.sheep.jiuyan.samllsheep.service.DownloadService;
 import com.sheep.jiuyan.samllsheep.service.FloatService;
 import com.sheep.jiuyan.samllsheep.service.FloatShotScreenService;
+import com.sheep.jiuyan.samllsheep.service.ListenerShotService;
 import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.SpUtils;
 import com.tencent.bugly.Bugly;
@@ -330,7 +331,6 @@ public class SheepApp extends MultiDexApplication {
      * Activity 生命周期监听,用于监控app前后台状态切换
      */
     ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
-        private ScreenShotListenManager manager;
 
         @Override
         public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
@@ -352,18 +352,7 @@ public class SheepApp extends MultiDexApplication {
                     Bugly.init(getApplicationContext(), Config.BUGLY_APPID, BuildConfig.DEBUG);
                 }
                 AppUsageManager.getInstance().needOpenLookAppUsageStatsPermisson(true);//尝试保存应用使用情况的数据
-                LogUtil.println("SheepApp onActivityCreated", mActivityCount);
-                if (DataUtil.IS_LISTEN_SCREEN_SHOT) {
-                    manager = ScreenShotListenManager.newInstance(activity.getApplicationContext());
-                    manager.setListener(
-                            new ScreenShotListenManager.OnScreenShotListener() {
-                                public void onShot(String imagePath) {
-                                    DataUtil.getInstance().addPng(imagePath);
-                                }
-                            }
-                    );
-                    manager.startListen();
-                }
+                LogUtil.println("SheepApp onActivityCreated", activity.getClass().getSimpleName(), mActivityCount);
                 UMConfigUtils.Event.SHEEP_CREATED.onEvent();
             }
         }
@@ -375,9 +364,12 @@ public class SheepApp extends MultiDexApplication {
             if (mActivityCount > 0) {
                 if (!notStop) {
                     notStop = true;
-                    LogUtil.println("SheepApp onActivityStarted", mActivityCount);
+                    LogUtil.println("SheepApp onActivityStarted", activity.getClass().getSimpleName(), mActivityCount);
                     UMConfigUtils.Event.SHEEP_STARTED.onEvent();
                     startService(new Intent(activity, DownloadService.class));
+                    if (DataUtil.IS_LISTEN_SCREEN_SHOT) {
+                        startService(new Intent(activity, ListenerShotService.class));
+                    }
                     Jump2View.getInstance().startFloat(activity, false);
                     Jump2View.getInstance().startShotScreenFloat(activity, false);
                 }
@@ -399,7 +391,7 @@ public class SheepApp extends MultiDexApplication {
             if (mActivityCount <= 0) {
                 if (notStop) {
                     notStop = false;
-                    LogUtil.println("SheepApp onActivityStopped", mActivityCount);
+                    LogUtil.println("SheepApp onActivityStopped", activity.getClass().getSimpleName(), mActivityCount);
                     UMConfigUtils.Event.SHEEP_STOPPED.onEvent();
                     Jump2View.getInstance().startFloat(activity, true);
                     Jump2View.getInstance().startShotScreenFloat(activity, true);
@@ -413,19 +405,19 @@ public class SheepApp extends MultiDexApplication {
 
         @Override
         public void onActivityDestroyed(Activity activity) {
-            Log.e("act_destroy_----", "in");
             if (!TextUtils.isEmpty(gamePackgeName) && isGameFlag() && (activity instanceof GameCertificationActivity || activity instanceof LoginAct)) {
                 CertificationUtil.newInstance().doCertification(activity, gamePackgeName, "cancel");
             }
             if (mActivityCount == 0) {
-                LogUtil.println("SheepApp onActivityDestroyed", mActivityCount);
+                LogUtil.println("SheepApp onActivityDestroyed", activity.getClass().getSimpleName(), mActivityCount);
                 DataUtil.getInstance().resetIsNewSmallSheep();
                 stopService(new Intent(SheepApp.this, DownloadService.class));
+//                if (DataUtil.IS_LISTEN_SCREEN_SHOT) {
+//                    stopService(new Intent(activity, ListenerShotService.class));
+//                }
                 stopService(new Intent(SheepApp.this, FloatService.class));
                 if (DataUtil.IS_USE_SCREEN_SHOT)
                     stopService(new Intent(SheepApp.this, FloatShotScreenService.class));
-                if (manager != null)
-                    manager.stopListen();
                 SpUtils.saveOrder("order", 1);
                 UMConfigUtils.Event.SHEEP_DESTROYED.onEvent();
             }
@@ -457,6 +449,7 @@ public class SheepApp extends MultiDexApplication {
         super.onLowMemory();
         /* 内存不足时让Glide清空内存缓存数据 */
         Glide.get(this).clearMemory();
+        LogUtil.println("SheepApp", "onLowMemory");
     }
 
     @Override
@@ -466,6 +459,7 @@ public class SheepApp extends MultiDexApplication {
             Glide.get(this).clearMemory();
         }
         Glide.get(this).onTrimMemory(level);
+        LogUtil.println("SheepApp", "onTrimMemory");
     }
 
     @Override

+ 2 - 2
app/src/main/java/com/sheep/jiuyan/samllsheep/service/FloatShotScreenService.java

@@ -250,7 +250,7 @@ public class FloatShotScreenService extends Service {
     private void performClick() {
         //获取当前正在运行的程序的包名
         //不判断是否是正在进行的任务上截图,只在上传截图的地方获取指定包名的截图
-        packageNameInForeground = DataUtil.getInstance().getPackageNameInForeground();
+        packageNameInForeground = ListenerShotService.getPackageNameInForeground(getApplicationContext());
         // 设置点击悬浮窗的响应
         startScreenShot();
     }
@@ -369,7 +369,7 @@ public class FloatShotScreenService extends Service {
         File fileImage = null;
         if (bitmap != null) {
             try {
-                fileImage = DataUtil.getInstance().getScreenShotsFile(packageNameInForeground);
+                fileImage = DataUtil.getScreenShotsFile(packageNameInForeground);
                 if (!fileImage.exists()) {
                     fileImage.createNewFile();
                 }

+ 187 - 0
app/src/main/java/com/sheep/jiuyan/samllsheep/service/ListenerShotService.java

@@ -0,0 +1,187 @@
+package com.sheep.jiuyan.samllsheep.service;
+
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.widget.RemoteViews;
+
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.util.RunningTaskUtil;
+import com.sheep.gamegroup.util.ScreenShotListenManager;
+import com.sheep.gamegroup.view.activity.ActMain;
+import com.sheep.jiuyan.samllsheep.R;
+import com.sheep.jiuyan.samllsheep.utils.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+
+/**
+ * Created by realicing on 2018/9/20.
+ * realicing@sina.com
+ */
+public class ListenerShotService extends Service {
+
+    private RunningTaskUtil runningTaskUtil;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        runningTaskUtil = new RunningTaskUtil(getApplicationContext());
+        manager = ScreenShotListenManager.newInstance(getApplicationContext());
+        manager.setListener(
+                new ScreenShotListenManager.OnScreenShotListener() {
+                    public void onShot(String imagePath) {
+                        addPng(imagePath);
+                    }
+                }
+        );
+        manager.startListen();
+
+        Notification notification = new Notification();
+        //通知栏没有展开时的显示内容
+        notification.icon = R.mipmap.icon;
+        notification.tickerText = "回到小绵羊";
+
+        //下拉通知栏的显示内容
+        notification.contentView = new RemoteViews(getPackageName() , R.layout.notification_sheep_shot_screen);
+
+        //点击通知栏跳转到相应的应用里面
+        Intent intent = new Intent(this , ActMain.class);
+        //这一句加不加没什么影响
+// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        notification.contentIntent = PendingIntent.getActivity(this , 1 , intent , 0);
+
+        //这里的id不能是0
+        startForeground(1 , notification);
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+    private ScreenShotListenManager manager;
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (manager != null)
+            manager.stopListen();
+    }
+
+
+    /**
+     * 获取前台运行的程序的包名
+     * @return
+     */
+    @SuppressLint("NewApi")
+    public String getPackageNameInForeground1(Context context) {
+        String topPackageName = runningTaskUtil.getTopRunningTasks();
+        if(TextUtils.isEmpty(topPackageName)){
+            return getAppProcessInfoInForeground(context);
+        }
+        return  topPackageName;
+    }
+
+    /**
+     * 获取前台运行的程序的包名
+     * @return
+     */
+    @SuppressLint("NewApi")
+    public static String getPackageNameInForeground(Context context) {
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
+            UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);//usagestats
+            long time = System.currentTimeMillis();
+            if (mUsageStatsManager != null) {
+                List<UsageStats> usageStatsList = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, time-5000L, time);
+
+                if (!ListUtil.isEmpty(usageStatsList)) {
+                    TreeMap<Long, UsageStats> mySortedMap = new TreeMap<>();
+                    for (UsageStats item : usageStatsList) {
+                        mySortedMap.put(item.getLastTimeUsed(), item);
+                    }
+
+                    UsageStats usageStats = mySortedMap.get(mySortedMap.lastKey());
+
+                    return usageStats.getPackageName();
+                }
+            }
+        }
+        return getAppProcessInfoInForeground(context);
+    }
+
+    private static String getAppProcessInfoInForeground(Context context) {
+        android.app.ActivityManager manager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        List<android.app.ActivityManager.RunningAppProcessInfo> processList = manager == null ? null : manager.getRunningAppProcesses();
+        if (!ListUtil.isEmpty(processList)) {
+            for (android.app.ActivityManager.RunningAppProcessInfo item : processList) {
+                if (item != null && item.importance == android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
+                    return item.processName;
+                }
+            }
+        }
+        return null;
+    }
+
+    public void addPng(final String imagePath) {
+        final String packageName = getPackageNameInForeground1(getApplicationContext());
+        if(TextUtils.isEmpty(packageName)){
+            LogUtil.println("ScreenShotListenManager", "无法获取到当前运行的应用的包名");
+            return;
+        }
+//        File shotFile = getScreenShotsFile(packageName);
+        LogUtil.println("ScreenShotListenManager", packageName);
+        Observable.just(1).delay(1, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new Action1<Integer>() {
+                    @Override
+                    public void call(Integer integer) {
+                        try {
+                            FileUtil.copyFileToDir(new File(imagePath), getScreenShotsDir(getApplicationContext(), packageName));
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                            LogUtil.println("ScreenShotListenManager", "复制截屏图片失败");
+                        }
+                    }
+                });
+
+    }
+    /**
+     * 截图目录
+     *
+     * @return
+     */
+    public static File getScreenShotsDir(Context context) {
+        return context.getDir("ScreenShots", Context.MODE_PRIVATE);
+    }
+    /**
+     * 指定程序的截图目录
+     *
+     * @return
+     */
+    public static File getScreenShotsDir(Context context, String packageName) {
+        File dir = new File(getScreenShotsDir(context), packageName);
+        if(!dir.exists())
+            dir.mkdirs();
+        return dir;
+    }
+
+}

+ 8 - 0
app/src/main/res/layout/act_sign_card.xml

@@ -99,6 +99,14 @@
             </RelativeLayout>
 
             <TextView
+                android:id="@+id/sign_card_time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:text="23:03:51后可打卡"
+                android:textColor="#ff999999"
+                android:textSize="14sp" />
+            <TextView
                 android:id="@+id/sign_card_title1"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"

+ 20 - 0
app/src/main/res/layout/notification_sheep_shot_screen.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center">
+
+    <ImageView
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_marginStart="20dp"
+        android:src="@mipmap/icon" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="点击回到小绵羊"
+        android:textColor="@color/black_333333"
+        android:textSize="18sp" />
+</LinearLayout>