Просмотр исходного кода

代理界面修改;消费详情界面优化

zengjiebin лет назад: 7
Родитель
Сommit
66d9b79196

+ 1 - 1
app/src/main/java/com/kfzs/duanduan/fragment/FgtPersonalCenter.java

@@ -207,7 +207,7 @@ public class FgtPersonalCenter extends BaseCompatFragment {
                 break;
             case R.id.proxy_service_layout://代理
                 if (!TextUtils.isEmpty(agentUrl))
-                    Jump2View.getInstance().goWeb(activity, agentUrl, "代理服务");
+                    Jump2View.getInstance().goWeb(activity, agentUrl, null);
                 else
                     G.showToast(R.string.loading_data);
                 break;

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

@@ -0,0 +1,62 @@
+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");
+        }
+    }
+}  

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

@@ -25,6 +25,8 @@ public class AppInfo {
 
     private String packageName;
 
+    private String className;
+
     public String getPackageName() {
         return packageName;
     }
@@ -33,6 +35,14 @@ public class AppInfo {
         this.packageName = packageName;
     }
 
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
     public Drawable getIcon() {
         return icon;
     }

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

@@ -752,7 +752,7 @@ public class Jump2View {
      * @param title
      */
     public void goWeb(Context context, String url, String title){
-        if(TextUtils.isEmpty(url) || TextUtils.isEmpty(title)){
+        if(TextUtils.isEmpty(url)){
             G.showToast(R.string.service_data_error);
             return;
         }

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

@@ -1,10 +1,12 @@
 package com.sheep.gamegroup.util;
 
 import android.app.Activity;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.provider.AlarmClock;
@@ -34,6 +36,7 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -314,6 +317,78 @@ public class SysAppUtil {
         }
     }
 
+    public static ComponentName getAppComponentName(String packageName) {
+
+        // 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
+        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
+        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        resolveIntent.setPackage(packageName);
+
+        // 通过getPackageManager()的queryIntentActivities方法遍历
+        List<ResolveInfo> resolveinfoList = SheepApp.getInstance().getPackageManager()
+                .queryIntentActivities(resolveIntent, 0);
+
+        ResolveInfo resolveinfo = null;
+        try {
+            resolveinfo = resolveinfoList.iterator().next();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (resolveinfo != null) {
+            // 这个就是我们要找的该APP的LAUNCHER的Activity[组织形式:packagename.mainActivityname]
+            String className = resolveinfo.activityInfo.name;
+            // LAUNCHER Intent
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.addCategory(Intent.CATEGORY_LAUNCHER);
+            // 设置ComponentName参数1:packagename参数2:MainActivity路径
+            ComponentName cn = new ComponentName(packageName, className);
+            return cn;
+        }
+        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);
+        }
+
+    }
+
+
+
+
+
     /**
      * 显示升级对话框
      * @param activity

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

@@ -273,15 +273,21 @@ public class TestUtil {
      * @param activity
      */
     public static void test(final Activity activity) {
-        final String[] items = {"h5跳转","新手对话框","md5","空间不足提示框","显示已经安装应用列表","复制token","复制faq地址","复制代理地址","复制世界杯地址","任务游戏列表","世界杯活动","交通银行信用卡测试", "浦发银行信用卡测试", "测试游戏模块","打卡成功提示","定向货币详情","提交身份认证时的提示", "检查标签", "友盟分享"};
+        final String[] items = {"测试代理页面","第三方应用使用情况","h5跳转","新手对话框","md5","空间不足提示框","显示已经安装应用列表","复制token","复制faq地址","复制代理地址","复制世界杯地址","任务游戏列表","世界杯活动","交通银行信用卡测试", "浦发银行信用卡测试", "测试游戏模块","打卡成功提示","定向货币详情","提交身份认证时的提示", "检查标签", "友盟分享"};
         AlertDialog dialog = new AlertDialog.Builder(activity).setTitle("请选择测试项目")
                 .setItems(items, new DialogInterface.OnClickListener() {
 
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         switch (items[which]) {
+                            case "测试代理页面":
+                                Jump2View.getInstance().goWeb(activity, "http://10.8.210.172:8081/#/?authorization=123123", null);
+                                break;
+                            case "第三方应用使用情况":
+                                SysAppUtil.getAppUsageStats(SysAppUtil.getAppComponentName(""));
+                                break;
                             case "h5跳转":
-                            Jump2View.getInstance().goXianwanWeb(activity,
+                                Jump2View.getInstance().goXianwanWeb(activity,
                                     "http://10.8.210.172:8095/test.js", "h5跳转");
                                 break;
                             case "新手对话框":

+ 16 - 36
app/src/main/java/com/sheep/gamegroup/view/activity/ActWeb.java

@@ -58,8 +58,10 @@ public class ActWeb extends BaseCompatActivity {
     WebView mWebView;
     @BindView(R.id.tv_next)
     TextView tv_next;
+    @BindView(R.id.layout_navigationBar)
+    View layout_navigationBar;
 
-    private String title;
+    private String title;//title为空时,不显示整个标题栏
     private String url;
     private WebSettings webViewSettings;
 
@@ -70,13 +72,17 @@ public class ActWeb extends BaseCompatActivity {
         setContentView(R.layout.activity_guide_on_hook);
 
         url = getIntent().getStringExtra("url");
-        title = getIntent().getStringExtra("title");
+        title = getIntent().getStringExtra("title");//title为空时,不显示整个标题栏
 
         ButterKnife.bind(this);
-        TitleBarUtils
-                .getInstance()
-                .setTitle(this, title == null ? "加载中" : title)
-                .setTitleFinish(this);
+        if(title == null){
+            layout_navigationBar.setVisibility(View.GONE);
+        } else {
+            TitleBarUtils
+                    .getInstance()
+                    .setTitle(this, TextUtils.isEmpty(title) ? "加载中" : title)
+                    .setTitleFinish(this);
+        }
         initWebViewSettings(mWebView);
         webViewSettings = mWebView.getSettings();
         webViewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
@@ -221,29 +227,6 @@ public class ActWeb extends BaseCompatActivity {
                 return true;
             }
 
-            @Override
-            public void onPageFinished(WebView view, String url) {
-                loadJs(view);
-                super.onPageFinished(view, url);
-            }
-
-            @Override
-            public void onLoadResource(WebView view, String url) {
-                loadJs(view);
-                super.onLoadResource(view, url);
-            }
-
-            @Override
-            public void onPageStarted(WebView view, String url, Bitmap favicon) {
-                loadJs(view);
-                super.onPageStarted(view, url, favicon);
-            }
-
-            @Override
-            public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
-                loadJs(view);
-                super.doUpdateVisitedHistory(view, url, isReload);
-            }
         });
         webViewSettings.setJavaScriptEnabled(true);
         mWebView.addJavascriptInterface(new KFZSJs(), "kfzsjs");
@@ -371,6 +354,10 @@ public class ActWeb extends BaseCompatActivity {
             }
             return "";
         }
+        @JavascriptInterface
+        public void goBack() {
+            finish();
+        }
 
     }
 
@@ -424,11 +411,4 @@ public class ActWeb extends BaseCompatActivity {
         }
     }
 
-    /**
-     * js 加载本地
-     */
-    private void loadJs(WebView webView){
-        String urls = "http://10.8.210.172:8095/test.js";
-//        webView.loadUrl(urls);
-    }
 }

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

@@ -1,7 +1,11 @@
 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;
 import com.umeng.socialize.UMShareAPI;
@@ -9,6 +13,9 @@ import com.umeng.socialize.UMShareAPI;
 import org.xutils.BuildConfig;
 import org.xutils.x;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
 import cn.jpush.android.api.JPushInterface;
 
 /**
@@ -32,5 +39,45 @@ 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");
     }
 }

+ 12 - 12
app/src/main/res/layout/app_info_item.xml

@@ -3,12 +3,12 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginTop="@dimen/content_padding_10"
+    android:layout_marginTop="@dimen/dp_10"
     android:background="@drawable/x_shap_shadow_bg_rectgangle_white"
-    android:paddingBottom="@dimen/content_padding_10"
+    android:paddingBottom="@dimen/dp_10"
     android:paddingEnd="@dimen/content_padding_20"
-    android:paddingStart="@dimen/content_padding_20"
-    android:paddingTop="@dimen/content_padding_20">
+    android:paddingStart="@dimen/dp_10"
+    android:paddingTop="@dimen/dp_10">
 
     <ImageView
         android:id="@+id/app_info_iv"
@@ -22,10 +22,10 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginStart="@dimen/content_padding_10"
+        android:layout_marginStart="@dimen/dp_10"
         android:text="名称"
         android:textColor="@color/black_6_3"
-        android:textSize="15sp"
+        android:textSize="12sp"
         app:layout_constraintBottom_toTopOf="@+id/app_info_size_tv"
         app:layout_constraintStart_toEndOf="@id/app_info_iv"
         app:layout_constraintTop_toTopOf="@+id/app_info_iv" />
@@ -37,7 +37,7 @@
         android:layout_gravity="center_vertical"
         android:text="包名"
         android:textColor="@color/black_191919"
-        android:textSize="15sp"
+        android:textSize="12sp"
         app:layout_constraintBottom_toTopOf="@+id/app_info_path_tv"
         app:layout_constraintStart_toStartOf="@+id/app_info_name_tv"
         app:layout_constraintTop_toBottomOf="@+id/app_info_name_tv" />
@@ -48,8 +48,8 @@
         android:layout_gravity="center_vertical"
         android:text="大小"
         android:textColor="@color/black_191919"
-        android:textSize="15sp"
-        android:layout_marginStart="@dimen/content_padding_10"
+        android:textSize="12sp"
+        android:layout_marginStart="@dimen/dp_10"
         app:layout_constraintBottom_toTopOf="@+id/app_info_path_tv"
         app:layout_constraintStart_toEndOf="@+id/app_info_package_name_tv"
         app:layout_constraintTop_toBottomOf="@+id/app_info_name_tv" />
@@ -61,7 +61,7 @@
         android:layout_gravity="center_vertical"
         android:text="路径"
         android:textColor="@color/black_deep"
-        android:textSize="15sp"
+        android:textSize="12sp"
         app:layout_constraintBottom_toBottomOf="@+id/app_info_iv"
         app:layout_constraintStart_toStartOf="@+id/app_info_name_tv"
         app:layout_constraintTop_toBottomOf="@+id/app_info_size_tv" />
@@ -73,7 +73,7 @@
         android:layout_gravity="center_vertical"
         android:text="系统应用"
         android:textColor="@color/black_deep"
-        android:textSize="15sp"
+        android:textSize="12sp"
         app:layout_constraintBottom_toTopOf="@+id/app_info_is_sd_tv"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintTop_toTopOf="@+id/app_info_iv" />
@@ -85,7 +85,7 @@
         android:layout_gravity="center_vertical"
         android:text="sd卡"
         android:textColor="@color/black_deep"
-        android:textSize="15sp"
+        android:textSize="12sp"
         app:layout_constraintBottom_toBottomOf="@+id/app_info_size_tv"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/app_info_is_sys_tv" />

+ 1 - 1
app/src/main/res/layout/dialog_orienteering_details.xml

@@ -12,7 +12,7 @@
             android:id="@+id/empty_view"
             layout="@layout/empty_view"
             android:layout_width="match_parent"
-            android:layout_height="300dp" />
+            android:layout_height="@dimen/orienteering_list_empty_gao" />
 
         <com.sheep.gamegroup.view.customview.RefreshLayout
             android:id="@+id/swipe_container"

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

@@ -86,4 +86,5 @@
 
 
     <dimen name="orienteering_item_gao">40dp</dimen>
+    <dimen name="orienteering_list_empty_gao">240dp</dimen>
 </resources>