diff --git a/README_CN.md b/README_CN.md index 97c7090..6ec21c0 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,5 +1,8 @@ [English](https://github.com/markzhai/AndroidPerformanceMonitor/blob/master/README.md) +# 修改说明 +本修正版删除了2个不需要的权限WRITE_EXTERNAL_STORAGE & READ_PHONE_STATE + # Android Performance Monitor [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.markzhai/blockcanary-android/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/com.github.markzhai/blockcanary-android) BlockCanary是一个Android平台的一个非侵入式的性能监控组件,应用只需要实现一个抽象类,提供一些该组件需要的上下文环境,就可以在平时使用应用的时候检测主线程上的各种卡慢问题,并通过组件提供的各种信息分析出原因并进行修复。 diff --git a/blockcanary-analyzer/build.gradle b/blockcanary-analyzer/build.gradle index 83af379..5e17a87 100644 --- a/blockcanary-analyzer/build.gradle +++ b/blockcanary-analyzer/build.gradle @@ -3,7 +3,6 @@ apply from: 'gradle-mvn-push.gradle' android { compileSdkVersion LIBRARY_COMPILE_SDK_VERSION - buildToolsVersion LIBRARY_BUILD_TOOLS_VERSION defaultConfig { minSdkVersion LIBRARY_MIN_SDK_VERSION @@ -14,11 +13,14 @@ android { buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + lintOptions { + checkAllWarnings true + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/blockcanary-analyzer/src/main/AndroidManifest.xml b/blockcanary-analyzer/src/main/AndroidManifest.xml index 36f52b2..bf633ac 100644 --- a/blockcanary-analyzer/src/main/AndroidManifest.xml +++ b/blockcanary-analyzer/src/main/AndroidManifest.xml @@ -3,8 +3,14 @@ xmlns:android="http://schemas.android.com/apk/res/android"> - - + + + + diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java index c1e3383..6b7e566 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java @@ -27,7 +27,7 @@ abstract class AbstractSampler { protected AtomicBoolean mShouldSample = new AtomicBoolean(false); protected long mSampleInterval; - private Runnable mRunnable = new Runnable() { + private final Runnable mRunnable = new Runnable() { @Override public void run() { doSample(); @@ -40,7 +40,7 @@ public void run() { }; public AbstractSampler(long sampleInterval) { - if (0 == sampleInterval) { + if ( sampleInterval <= 0 ) { sampleInterval = DEFAULT_SAMPLE_INTERVAL; } mSampleInterval = sampleInterval; @@ -53,8 +53,7 @@ public void start() { mShouldSample.set(true); HandlerThreadFactory.getTimerThreadHandler().removeCallbacks(mRunnable); - HandlerThreadFactory.getTimerThreadHandler().postDelayed(mRunnable, - BlockCanaryInternals.getInstance().getSampleDelay()); + HandlerThreadFactory.getTimerThreadHandler().postDelayed(mRunnable, BlockCanaryInternals.getInstance().getSampleDelay()); } public void stop() { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java index 895d0d6..0d9095e 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java @@ -15,6 +15,7 @@ */ package com.github.moduth.blockcanary; +import android.os.Build; import android.os.Environment; import android.os.Looper; @@ -35,13 +36,11 @@ public final class BlockCanaryInternals { private static BlockCanaryInternals sInstance; private static BlockCanaryContext sContext; - private List mInterceptorChain = new LinkedList<>(); + private final List mInterceptorChain = new LinkedList<>(); public BlockCanaryInternals() { - stackSampler = new StackSampler( - Looper.getMainLooper().getThread(), - sContext.provideDumpInterval()); + stackSampler = new StackSampler(Looper.getMainLooper().getThread(), sContext.provideDumpInterval()); cpuSampler = new CpuSampler(sContext.provideDumpInterval()); @@ -59,6 +58,7 @@ public void onBlockEvent(long realTimeStart, long realTimeEnd, .setCpuBusyFlag(cpuSampler.isCpuBusy(realTimeStart, realTimeEnd)) .setRecentCpuRate(cpuSampler.getCpuRateInfo()) .setThreadStackEntries(threadStackEntries) + .setStackTraceElements(stackSampler.getTraceElements()) .flushString(); LogWriter.save(blockInfo.toString()); @@ -117,12 +117,18 @@ long getSampleDelay() { static String getPath() { String state = Environment.getExternalStorageState(); - String logPath = BlockCanaryInternals.getContext() - == null ? "" : BlockCanaryInternals.getContext().providePath(); + String logPath = BlockCanaryInternals.getContext() == null ? "" : + BlockCanaryInternals.getContext().providePath(); - if (Environment.MEDIA_MOUNTED.equals(state) - && Environment.getExternalStorageDirectory().canWrite()) { - return Environment.getExternalStorageDirectory().getPath() + logPath; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (Environment.MEDIA_MOUNTED.equals(state) ) { + return BlockCanaryInternals.getContext().provideContext().getExternalFilesDir(logPath).getPath(); + } + }else{ + if (Environment.MEDIA_MOUNTED.equals(state) + && Environment.getExternalStorageDirectory().canWrite()) { + return Environment.getExternalStorageDirectory().getPath() + logPath; + } } return getContext().provideContext().getFilesDir() + BlockCanaryInternals.getContext().providePath(); } @@ -145,7 +151,7 @@ public static File[] getLogFiles() { private static class BlockLogFileFilter implements FilenameFilter { - private String TYPE = ".log"; + private final String TYPE = ".log"; BlockLogFileFilter() { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java index 86c966d..de89b2f 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java @@ -15,8 +15,8 @@ */ package com.github.moduth.blockcanary; +import android.os.Build; import android.util.Log; - import com.github.moduth.blockcanary.internal.BlockInfo; import java.io.BufferedReader; @@ -56,8 +56,10 @@ public CpuSampler(long sampleInterval) { @Override public void start() { - super.start(); - reset(); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + super.start(); + reset(); + } } /** diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java index bf4c26d..cf552be 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java @@ -20,8 +20,8 @@ final class HandlerThreadFactory { - private static HandlerThreadWrapper sLoopThread = new HandlerThreadWrapper("loop"); - private static HandlerThreadWrapper sWriteLogThread = new HandlerThreadWrapper("writer"); + private static final HandlerThreadWrapper sLoopThread = new HandlerThreadWrapper("loop"); + private static final HandlerThreadWrapper sWriteLogThread = new HandlerThreadWrapper("writer"); private HandlerThreadFactory() { throw new InstantiationError("Must not instantiate this class"); @@ -36,7 +36,7 @@ public static Handler getWriteLogThreadHandler() { } private static class HandlerThreadWrapper { - private Handler handler = null; + private final Handler handler; public HandlerThreadWrapper(String threadName) { HandlerThread handlerThread = new HandlerThread("BlockCanary-" + threadName); diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java index 3b697e6..ee5b41a 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java @@ -21,12 +21,10 @@ class LooperMonitor implements Printer { - private static final int DEFAULT_BLOCK_THRESHOLD_MILLIS = 3000; - - private long mBlockThresholdMillis = DEFAULT_BLOCK_THRESHOLD_MILLIS; + private long mBlockThresholdMillis; private long mStartTimestamp = 0; private long mStartThreadTimestamp = 0; - private BlockListener mBlockListener = null; + private BlockListener mBlockListener; private boolean mPrintingStarted = false; private final boolean mStopWhenDebugging; @@ -83,21 +81,21 @@ public void run() { } private void startDump() { - if (null != BlockCanaryInternals.getInstance().stackSampler) { + if (BlockCanaryInternals.getInstance().stackSampler != null) { BlockCanaryInternals.getInstance().stackSampler.start(); } - if (null != BlockCanaryInternals.getInstance().cpuSampler) { + if (BlockCanaryInternals.getInstance().cpuSampler != null) { BlockCanaryInternals.getInstance().cpuSampler.start(); } } private void stopDump() { - if (null != BlockCanaryInternals.getInstance().stackSampler) { + if (BlockCanaryInternals.getInstance().stackSampler != null) { BlockCanaryInternals.getInstance().stackSampler.stop(); } - if (null != BlockCanaryInternals.getInstance().cpuSampler) { + if (BlockCanaryInternals.getInstance().cpuSampler != null) { BlockCanaryInternals.getInstance().cpuSampler.stop(); } } diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java index 2d65e4a..ca7cc2d 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java @@ -28,8 +28,16 @@ class StackSampler extends AbstractSampler { private static final int DEFAULT_MAX_ENTRY_COUNT = 100; private static final LinkedHashMap sStackMap = new LinkedHashMap<>(); - private int mMaxEntryCount = DEFAULT_MAX_ENTRY_COUNT; - private Thread mCurrentThread; + private final int mMaxEntryCount; + private final Thread mCurrentThread; + + public StackTraceElement[] getTraceElements() { + synchronized (sStackMap) { + return traceElements; + } + } + + private static StackTraceElement[] traceElements; public StackSampler(Thread thread, long sampleIntervalMillis) { this(thread, DEFAULT_MAX_ENTRY_COUNT, sampleIntervalMillis); @@ -59,8 +67,8 @@ public ArrayList getThreadStackEntries(long startTime, long endTime) { @Override protected void doSample() { StringBuilder stringBuilder = new StringBuilder(); - - for (StackTraceElement stackTraceElement : mCurrentThread.getStackTrace()) { + traceElements = mCurrentThread.getStackTrace(); + for (StackTraceElement stackTraceElement : traceElements) { stringBuilder .append(stackTraceElement.toString()) .append(BlockInfo.SEPARATOR); diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java index 1b07edd..f78058d 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java @@ -19,7 +19,7 @@ import android.content.pm.PackageInfo; import android.os.Build; import android.os.Build.VERSION; -import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import com.github.moduth.blockcanary.BlockCanaryInternals; @@ -46,7 +46,6 @@ public class BlockInfo { public static final String KEY_QUA = "qua"; public static final String KEY_MODEL = "model"; public static final String KEY_API = "api-level"; - public static final String KEY_IMEI = "imei"; public static final String KEY_UID = "uid"; public static final String KEY_CPU_CORE = "cpu-core"; public static final String KEY_CPU_BUSY = "cpu-busy"; @@ -63,20 +62,14 @@ public class BlockInfo { public static final String KEY_TOTAL_MEMORY = "totalMemory"; public static final String KEY_FREE_MEMORY = "freeMemory"; - public static String sQualifier; - public static String sModel; - public static String sApiLevel = ""; - /** - * The International Mobile Equipment Identity or IMEI /aɪˈmiː/ is a number, - * usually unique, to identify 3GPP and iDEN mobile phones - */ - public static String sImei = ""; - public static int sCpuCoreNum = -1; + public static final String sQualifier; + public static final String sModel; + public static final String sApiLevel; + public static final int sCpuCoreNum; public String qualifier; public String model; public String apiLevel = ""; - public String imei = ""; public int cpuCoreNum = -1; // Per Block Info fields @@ -94,28 +87,18 @@ public class BlockInfo { public boolean cpuBusy; public String cpuRateInfo; public ArrayList threadStackEntries = new ArrayList<>(); + public StackTraceElement[] stackTraceElements ; - private StringBuilder basicSb = new StringBuilder(); - private StringBuilder cpuSb = new StringBuilder(); - private StringBuilder timeSb = new StringBuilder(); - private StringBuilder stackSb = new StringBuilder(); - private static final String EMPTY_IMEI = "empty_imei"; + private final StringBuilder basicSb = new StringBuilder(); + private final StringBuilder cpuSb = new StringBuilder(); + private final StringBuilder timeSb = new StringBuilder(); + private final StringBuilder stackSb = new StringBuilder(); static { sCpuCoreNum = PerformanceUtils.getNumCores(); sModel = Build.MODEL; sApiLevel = Build.VERSION.SDK_INT + " " + VERSION.RELEASE; sQualifier = BlockCanaryInternals.getContext().provideQualifier(); - try { - TelephonyManager telephonyManager = (TelephonyManager) BlockCanaryInternals - .getContext() - .provideContext() - .getSystemService(Context.TELEPHONY_SERVICE); - sImei = telephonyManager.getDeviceId(); - } catch (Exception exception) { - Log.e(TAG, NEW_INSTANCE_METHOD, exception); - sImei = EMPTY_IMEI; - } } public BlockInfo() { @@ -124,7 +107,7 @@ public BlockInfo() { public static BlockInfo newInstance() { BlockInfo blockInfo = new BlockInfo(); Context context = BlockCanaryInternals.getContext().provideContext(); - if (blockInfo.versionName == null || blockInfo.versionName.length() == 0) { + if (TextUtils.isEmpty(blockInfo.versionName)) { try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); blockInfo.versionCode = info.versionCode; @@ -138,7 +121,6 @@ public static BlockInfo newInstance() { blockInfo.model = sModel; blockInfo.apiLevel = sApiLevel; blockInfo.qualifier = sQualifier; - blockInfo.imei = sImei; blockInfo.uid = BlockCanaryInternals.getContext().provideUid(); blockInfo.processName = ProcessUtils.myProcessName(); blockInfo.network = BlockCanaryInternals.getContext().provideNetworkType(); @@ -163,6 +145,11 @@ public BlockInfo setThreadStackEntries(ArrayList threadStackEntries) { return this; } + public BlockInfo setStackTraceElements(StackTraceElement[] stackTraceElements) { + this.stackTraceElements = stackTraceElements; + return this; + } + public BlockInfo setMainThreadTimeCost(long realTimeStart, long realTimeEnd, long threadTimeStart, long threadTimeEnd) { timeCost = realTimeEnd - realTimeStart; threadTimeCost = threadTimeEnd - threadTimeStart; @@ -176,7 +163,6 @@ public BlockInfo flushString() { basicSb.append(KEY_QUA).append(KV).append(qualifier).append(separator); basicSb.append(KEY_VERSION_NAME).append(KV).append(versionName).append(separator); basicSb.append(KEY_VERSION_CODE).append(KV).append(versionCode).append(separator); - basicSb.append(KEY_IMEI).append(KV).append(imei).append(separator); basicSb.append(KEY_UID).append(KV).append(uid).append(separator); basicSb.append(KEY_NETWORK).append(KV).append(network).append(separator); basicSb.append(KEY_MODEL).append(KV).append(model).append(separator); @@ -220,4 +206,22 @@ public String getTimeString() { public String toString() { return String.valueOf(basicSb) + timeSb + cpuSb + stackSb; } + + public Exception buildException(){ + StringBuilder sb = new StringBuilder("threadTimeCost time cost:") + .append(threadTimeCost) + .append("ms,real time cost:") + .append(timeCost) + .append("ms"); + if(timeCost - threadTimeCost > 300){ + sb.append(",thread waiting a long time!!!"); + } + if(cpuBusy){ + sb.append(",cpu is busy !!!"); + } + Exception exception = new BlockcanaryException(sb.toString()); + exception.setStackTrace(stackTraceElements); + return exception; + + } } diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockcanaryException.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockcanaryException.java new file mode 100644 index 0000000..86fe7f8 --- /dev/null +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockcanaryException.java @@ -0,0 +1,19 @@ +package com.github.moduth.blockcanary.internal; + +public class BlockcanaryException extends Exception{ + + public BlockcanaryException() { + } + + public BlockcanaryException(String detailMessage) { + super(detailMessage); + } + + public BlockcanaryException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + } + + public BlockcanaryException(Throwable throwable) { + super(throwable); + } +} diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/NetUtils.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/NetUtils.java new file mode 100644 index 0000000..448ce67 --- /dev/null +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/NetUtils.java @@ -0,0 +1,164 @@ +package com.github.moduth.blockcanary.internal; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.telephony.TelephonyManager; + +@SuppressWarnings({ "deprecation", "RedundantSuppression" }) +public class NetUtils { + /** + * 没有网络连接 + */ + public static final String NETWORK_NONE = "NONE"; + /** + * wifi连接 + */ + public static final String NETWORK_WIFI = "WIFI"; + /** + * 2G + */ + public static final String NETWORK_2G = "2G"; + /** + * 3G + */ + public static final String NETWORK_3G = "3G"; + /** + * 4G + */ + public static final String NETWORK_4G = "4G"; + /** + * 手机流量 + */ + public static final String NETWORK_MOBILE = "MOBILE"; + + /** + * 获取运营商名字 + * + * @param context context + * @return int + */ + public static String getOperatorName(Context context) { + /* + * getSimOperatorName()就可以直接获取到运营商的名字 + * 也可以使用IMSI获取,getSimOperator(),然后根据返回值判断,例如"46000"为移动 + * IMSI相关链接:http://baike.baidu.com/item/imsi + */ + TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + // getSimOperatorName就可以直接获取到运营商的名字 + return telephonyManager.getSimOperatorName(); + } + + /** + * 获取当前网络连接的类型 + * + * @param context context + * @return int + */ + public static String getNetworkType(Context context) { + ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context + .CONNECTIVITY_SERVICE); + if (null == connManager) { + return NETWORK_NONE; + } + // 获取网络类型,如果为空,返回无网络 + NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo(); + if (activeNetInfo == null || !activeNetInfo.isAvailable()) { + return NETWORK_NONE; + } + // 判断是否为WIFI + NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + if (null != wifiInfo) { + NetworkInfo.State state = wifiInfo.getState(); + if (null != state) { + if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) { + return NETWORK_WIFI; + } + } + } + // 若不是WIFI,则去判断是2G、3G、4G网 + TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + int networkType = telephonyManager.getNetworkType(); + switch (networkType) { + /* + GPRS : 2G(2.5) General Packet Radia Service 114kbps + EDGE : 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps + UMTS : 3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准 + CDMA : 2G 电信 Code Division Multiple Access 码分多址 + EVDO_0 : 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G + EVDO_A : 3G 1.8mbps - 3.1mbps 属于3G过渡,3.5G + 1xRTT : 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡, + HSDPA : 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps + HSUPA : 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps + HSPA : 3G (分HSDPA,HSUPA) High Speed Packet Access + IDEN : 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科) + EVDO_B : 3G EV-DO Rev.B 14.7Mbps 下行 3.5G + LTE : 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G + EHRPD : 3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级 + HSPAP : 3G HSPAP 比 HSDPA 快些 + */ + // 2G网络 + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_1xRTT: + case TelephonyManager.NETWORK_TYPE_IDEN: + return NETWORK_2G; + // 3G网络 + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_HSPAP: + return NETWORK_3G; + // 4G网络 + case TelephonyManager.NETWORK_TYPE_LTE: + return NETWORK_4G; + default: + return NETWORK_MOBILE; + } + } + + /** + * 判断网络是否连接 + * + * @param context context + * @return true/false + */ + public static boolean isNetConnected(Context context) { + ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity != null) { + NetworkInfo info = connectivity.getActiveNetworkInfo(); + if (info != null && info.isConnected()) { + return info.getState() == NetworkInfo.State.CONNECTED; + } + } + return false; + } + + /** + * 判断是否wifi连接 + * + * @param context context + * @return true/false + */ + public static synchronized boolean isWifiConnected(Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context + .CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); + if (networkInfo != null) { + int networkInfoType = networkInfo.getType(); + if (networkInfoType == ConnectivityManager.TYPE_WIFI || networkInfoType == ConnectivityManager + .TYPE_ETHERNET) { + return networkInfo.isConnected(); + } + } + } + return false; + } +} diff --git a/blockcanary-android-no-op/build.gradle b/blockcanary-android-no-op/build.gradle index 83af379..5e17a87 100644 --- a/blockcanary-android-no-op/build.gradle +++ b/blockcanary-android-no-op/build.gradle @@ -3,7 +3,6 @@ apply from: 'gradle-mvn-push.gradle' android { compileSdkVersion LIBRARY_COMPILE_SDK_VERSION - buildToolsVersion LIBRARY_BUILD_TOOLS_VERSION defaultConfig { minSdkVersion LIBRARY_MIN_SDK_VERSION @@ -14,11 +13,14 @@ android { buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + lintOptions { + checkAllWarnings true + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/blockcanary-android-no-op/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java b/blockcanary-android-no-op/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java index 278a8c7..0dbd64f 100644 --- a/blockcanary-android-no-op/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java +++ b/blockcanary-android-no-op/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java @@ -1,4 +1,23 @@ package com.github.moduth.blockcanary.internal; public class BlockInfo { + public Exception buildException(){ + return null; + } + + public String getBasicString() { + return ""; + } + + public String getCpuString() { + return ""; + } + + public String getTimeString() { + return ""; + } + + public String toString() { + return ""; + } } diff --git a/blockcanary-android/build.gradle b/blockcanary-android/build.gradle index ebe613e..11764b3 100644 --- a/blockcanary-android/build.gradle +++ b/blockcanary-android/build.gradle @@ -3,7 +3,6 @@ apply from: 'gradle-mvn-push.gradle' android { compileSdkVersion LIBRARY_COMPILE_SDK_VERSION - buildToolsVersion LIBRARY_BUILD_TOOLS_VERSION defaultConfig { minSdkVersion LIBRARY_MIN_SDK_VERSION @@ -14,13 +13,18 @@ android { buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + lintOptions { + checkAllWarnings true + } } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') -// compile project(':blockcanary-analyzer') - compile 'com.github.markzhai:blockcanary-analyzer:1.5.0' + implementation fileTree(dir: 'libs', include: ['*.jar']) + api project(':blockcanary-analyzer') + //implementation 'com.github.markzhai:blockcanary-analyzer:1.5.0' + implementation 'androidx.core:core:1.1.0' + implementation "androidx.preference:preference:1.1.0" } diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java index edc0858..e80d322 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java @@ -15,11 +15,15 @@ */ package com.github.moduth.blockcanary; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; +import android.graphics.Color; +import android.os.Build; import android.os.Looper; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import com.github.moduth.blockcanary.ui.DisplayActivity; @@ -33,9 +37,10 @@ public final class BlockCanary { private static final String TAG = "BlockCanary"; - + // these lines are originally copied from LeakCanary: Copyright (C) 2015 Square, Inc. + private static final Executor fileIoExecutor = newSingleThreadExecutor("File-IO"); private static BlockCanary sInstance; - private BlockCanaryInternals mBlockCanaryCore; + private final BlockCanaryInternals mBlockCanaryCore; private boolean mMonitorStarted = false; private BlockCanary() { @@ -57,6 +62,7 @@ private BlockCanary() { * @return {@link BlockCanary} */ public static BlockCanary install(Context context, BlockCanaryContext blockCanaryContext) { + createNotificationChannel(context); BlockCanaryContext.init(context, blockCanaryContext); setEnabled(context, DisplayActivity.class, BlockCanaryContext.get().displayNotification()); return get(); @@ -78,6 +84,52 @@ public static BlockCanary get() { return sInstance; } + private static void setEnabledBlocking(Context appContext, + Class componentClass, + boolean enabled) { + ComponentName component = new ComponentName(appContext, componentClass); + PackageManager packageManager = appContext.getPackageManager(); + int newState = enabled ? COMPONENT_ENABLED_STATE_ENABLED : COMPONENT_ENABLED_STATE_DISABLED; + // Blocks on IPC. + packageManager.setComponentEnabledSetting(component, newState, DONT_KILL_APP); + } + + private static void executeOnFileIoThread(Runnable runnable) { + fileIoExecutor.execute(runnable); + } + + private static Executor newSingleThreadExecutor(String threadName) { + return Executors.newSingleThreadExecutor(new SingleThreadFactory(threadName)); + } + + private static void setEnabled(Context context, + final Class componentClass, + final boolean enabled) { + final Context appContext = context.getApplicationContext(); + executeOnFileIoThread(new Runnable() { + @Override + public void run() { + setEnabledBlocking(appContext, componentClass, enabled); + } + }); + } + + private static void createNotificationChannel(Context context) { + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel(DisplayService.CHANNEL_ID, "Block Canary", importance); + channel.enableLights(true); + channel.setDescription("Block Canary"); + channel.setLightColor(Color.RED); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + if(notificationManager != null) notificationManager.createNotificationChannel(channel); + } + } + /** * Start monitoring. */ @@ -99,6 +151,7 @@ public void stop() { mBlockCanaryCore.cpuSampler.stop(); } } + // end of lines copied from LeakCanary /** * Zip and upload log files, will user context's zip and log implementation. @@ -130,38 +183,4 @@ public boolean isMonitorDurationEnd() { return startTime != 0 && System.currentTimeMillis() - startTime > BlockCanaryContext.get().provideMonitorDuration() * 3600 * 1000; } - - // these lines are originally copied from LeakCanary: Copyright (C) 2015 Square, Inc. - private static final Executor fileIoExecutor = newSingleThreadExecutor("File-IO"); - - private static void setEnabledBlocking(Context appContext, - Class componentClass, - boolean enabled) { - ComponentName component = new ComponentName(appContext, componentClass); - PackageManager packageManager = appContext.getPackageManager(); - int newState = enabled ? COMPONENT_ENABLED_STATE_ENABLED : COMPONENT_ENABLED_STATE_DISABLED; - // Blocks on IPC. - packageManager.setComponentEnabledSetting(component, newState, DONT_KILL_APP); - } - // end of lines copied from LeakCanary - - private static void executeOnFileIoThread(Runnable runnable) { - fileIoExecutor.execute(runnable); - } - - private static Executor newSingleThreadExecutor(String threadName) { - return Executors.newSingleThreadExecutor(new SingleThreadFactory(threadName)); - } - - private static void setEnabled(Context context, - final Class componentClass, - final boolean enabled) { - final Context appContext = context.getApplicationContext(); - executeOnFileIoThread(new Runnable() { - @Override - public void run() { - setEnabledBlocking(appContext, componentClass, enabled); - } - }); - } } diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java index 7d71590..26d4426 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java @@ -15,74 +15,50 @@ */ package com.github.moduth.blockcanary; -import android.annotation.TargetApi; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.util.Log; +import androidx.core.app.NotificationCompat; import com.github.moduth.blockcanary.internal.BlockInfo; import com.github.moduth.blockcanary.ui.DisplayActivity; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES.HONEYCOMB; -import static android.os.Build.VERSION_CODES.JELLY_BEAN; - final class DisplayService implements BlockInterceptor { private static final String TAG = "DisplayService"; + public static final String CHANNEL_ID = "BLOCK_CANARY"; @Override public void onBlock(Context context, BlockInfo blockInfo) { Intent intent = new Intent(context, DisplayActivity.class); intent.putExtra("show_latest", blockInfo.timeStart); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT); String contentTitle = context.getString(R.string.block_canary_class_has_blocked, blockInfo.timeStart); String contentText = context.getString(R.string.block_canary_notification_message); show(context, contentTitle, contentText, pendingIntent); } - @TargetApi(HONEYCOMB) private void show(Context context, String contentTitle, String contentText, PendingIntent pendingIntent) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - Notification notification; - if (SDK_INT < HONEYCOMB) { - notification = new Notification(); - notification.icon = R.drawable.block_canary_notification; - notification.when = System.currentTimeMillis(); - notification.flags |= Notification.FLAG_AUTO_CANCEL; - notification.defaults = Notification.DEFAULT_SOUND; - try { - Method deprecatedMethod = notification.getClass().getMethod("setLatestEventInfo", Context.class, CharSequence.class, CharSequence.class, PendingIntent.class); - deprecatedMethod.invoke(notification, context, contentTitle, contentText, pendingIntent); - } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException - | InvocationTargetException e) { - Log.w(TAG, "Method not found", e); - } - } else { - Notification.Builder builder = new Notification.Builder(context) + if(notificationManager != null) { + Notification notification; + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.block_canary_notification) .setWhen(System.currentTimeMillis()) .setContentTitle(contentTitle) .setContentText(contentText) .setAutoCancel(true) .setContentIntent(pendingIntent) - .setDefaults(Notification.DEFAULT_SOUND); - if (SDK_INT < JELLY_BEAN) { - notification = builder.getNotification(); - } else { - notification = builder.build(); - } + .setDefaults(Notification.DEFAULT_SOUND) + .setPriority(NotificationCompat.PRIORITY_DEFAULT); + + notification = builder.build(); + notificationManager.notify(0xDEAFBEEF, notification); } - notificationManager.notify(0xDEAFBEEF, notification); } } diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java index 195b0ce..b08248e 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java @@ -11,17 +11,19 @@ final class BlockCanaryUtils { - private static final List WHITE_LIST = new LinkedList<>(); - private static final List CONCERN_LIST = new LinkedList<>(); + private static final List sWhiteList = new LinkedList<>(); + private static final List sConcernList = new LinkedList<>(); static { - WHITE_LIST.addAll(BlockCanaryInternals.getContext().provideWhiteList()); + if (BlockCanaryInternals.getContext().provideWhiteList() != null) { + sWhiteList.addAll(BlockCanaryInternals.getContext().provideWhiteList()); + } if (BlockCanaryInternals.getContext().concernPackages() != null) { - CONCERN_LIST.addAll(BlockCanaryInternals.getContext().concernPackages()); + sConcernList.addAll(BlockCanaryInternals.getContext().concernPackages()); } - if (CONCERN_LIST.isEmpty()) { - CONCERN_LIST.add(ProcessUtils.myProcessName()); + if (sConcernList.isEmpty()) { + sConcernList.add(ProcessUtils.myProcessName()); } } @@ -56,7 +58,7 @@ public static boolean isInWhiteList(BlockInfo info) { if (Character.isLetter(stackEntry.charAt(0))) { String[] lines = stackEntry.split(BlockInfo.SEPARATOR); for (String line : lines) { - for (String whiteListEntry : WHITE_LIST) { + for (String whiteListEntry : sWhiteList) { if (line.startsWith(whiteListEntry)) { return true; } @@ -68,11 +70,11 @@ public static boolean isInWhiteList(BlockInfo info) { } public static List getConcernPackages() { - return CONCERN_LIST; + return sConcernList; } private static String concernStackString(String line) { - for (String concernPackage : CONCERN_LIST) { + for (String concernPackage : sConcernList) { if (line.startsWith(concernPackage)) { return classSimpleName(line); } diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockInfoEx.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockInfoEx.java index 4733b69..fa6b93a 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockInfoEx.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockInfoEx.java @@ -38,8 +38,6 @@ public static BlockInfoEx newInstance(File file) { blockInfo.model = line.split(KV)[1]; } else if (line.startsWith(KEY_API)) { blockInfo.apiLevel = line.split(KV)[1]; - } else if (line.startsWith(KEY_IMEI)) { - blockInfo.imei = line.split(KV)[1]; } else if (line.startsWith(KEY_CPU_CORE)) { blockInfo.cpuCoreNum = Integer.valueOf(line.split(KV)[1]); } else if (line.startsWith(KEY_UID)) { diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DetailAdapter.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DetailAdapter.java index c1599c3..353f67b 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DetailAdapter.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DetailAdapter.java @@ -16,7 +16,7 @@ package com.github.moduth.blockcanary.ui; import android.content.Context; -import android.text.Html; +import androidx.core.text.HtmlCompat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -47,15 +47,13 @@ public View getView(int position, View convertView, ViewGroup parent) { Context context = parent.getContext(); if (getItemViewType(position) == TOP_ROW) { if (convertView == null) { - convertView = - LayoutInflater.from(context).inflate(R.layout.block_canary_ref_top_row, parent, false); + convertView = LayoutInflater.from(context).inflate(R.layout.block_canary_ref_top_row, parent, false); } TextView textView = findById(convertView, R.id.__leak_canary_row_text); textView.setText(context.getPackageName()); } else { if (convertView == null) { - convertView = - LayoutInflater.from(context).inflate(R.layout.block_canary_ref_row, parent, false); + convertView = LayoutInflater.from(context).inflate(R.layout.block_canary_ref_row, parent, false); } TextView textView = findById(convertView, R.id.__leak_canary_row_text); @@ -65,7 +63,7 @@ public View getView(int position, View convertView, ViewGroup parent) { if (isThreadStackEntry && !mFoldings[position]) { htmlString += " " + "blocked" + ""; } - textView.setText(Html.fromHtml(htmlString)); + textView.setText(HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_LEGACY)); DisplayConnectorView connectorView = findById(convertView, R.id.__leak_canary_row_connector); connectorView.setType(connectorViewType(position)); @@ -78,9 +76,8 @@ public View getView(int position, View convertView, ViewGroup parent) { } private DisplayConnectorView.Type connectorViewType(int position) { - return (position == 1) ? DisplayConnectorView.Type.START : ( - (position == getCount() - 1) ? DisplayConnectorView.Type.END : - DisplayConnectorView.Type.NODE); + return (position == 1) ? DisplayConnectorView.Type.START : ((position == getCount() - 1) + ? DisplayConnectorView.Type.END : DisplayConnectorView.Type.NODE); } private String elementToHtmlString(String element, int position, boolean folding) { diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java index cdd30b8..28bdfc6 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java @@ -23,25 +23,14 @@ import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.Button; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.TextView; - +import android.view.*; +import android.widget.*; import com.github.moduth.blockcanary.BlockCanaryContext; import com.github.moduth.blockcanary.BlockCanaryInternals; import com.github.moduth.blockcanary.LogWriter; @@ -68,7 +57,7 @@ public class DisplayActivity extends Activity { private static final String TAG = "DisplayActivity"; private static final String SHOW_BLOCK_EXTRA = "show_latest"; - public static final String SHOW_BLOCK_EXTRA_KEY = "BlockStartTime"; + private static final String SHOW_BLOCK_EXTRA_KEY = "BlockStartTime"; // empty until it's been first loaded. private List mBlockInfoEntries = new ArrayList<>(); @@ -101,9 +90,9 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.block_canary_display_leak); - mListView = (ListView) findViewById(R.id.__leak_canary_display_leak_list); - mFailureView = (TextView) findViewById(R.id.__leak_canary_display_leak_failure); - mActionButton = (Button) findViewById(R.id.__leak_canary_action); + mListView = findViewById(R.id.__leak_canary_display_leak_list); + mFailureView = findViewById(R.id.__leak_canary_display_leak_failure); + mActionButton = findViewById(R.id.__leak_canary_action); mMaxStoredBlockCount = getResources().getInteger(R.integer.block_canary_max_stored_count); @@ -199,10 +188,7 @@ private void shareBlock(BlockInfoEx blockInfo) { private void shareHeapDump(BlockInfoEx blockInfo) { File heapDumpFile = blockInfo.logFile; - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - heapDumpFile.setReadable(true, false); - } + heapDumpFile.setReadable(true, false); Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("application/octet-stream"); intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(heapDumpFile)); @@ -240,12 +226,10 @@ public void onItemClick(AdapterView parent, View view, int position, long id) updateUi(); } }); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - invalidateOptionsMenu(); - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(false); - } + invalidateOptionsMenu(); + ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(false); } setTitle(getString(R.string.block_canary_block_list_title, getPackageName())); mActionButton.setText(R.string.block_canary_delete_all); @@ -287,12 +271,10 @@ public void onItemClick(AdapterView parent, View view, int position, long id) adapter.toggleRow(position); } }); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - invalidateOptionsMenu(); - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - } + invalidateOptionsMenu(); + ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); } mActionButton.setVisibility(VISIBLE); mActionButton.setText(R.string.block_canary_delete); @@ -309,7 +291,7 @@ public void onClick(View v) { } }); adapter.update(blockInfo); - setTitle(getString(R.string.block_canary_class_has_blocked, blockInfo.timeCost)); + setTitle(getString(R.string.block_canary_class_has_blocked, Long.toString(blockInfo.timeCost))); } private BlockInfoEx getBlock(String startTime) { @@ -317,7 +299,7 @@ private BlockInfoEx getBlock(String startTime) { return null; } for (BlockInfoEx blockInfo : mBlockInfoEntries) { - if (blockInfo.timeStart != null && startTime.equals(blockInfo.timeStart)) { + if (startTime.equals(blockInfo.timeStart)) { return blockInfo; } } @@ -347,8 +329,8 @@ public View getView(int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.from(DisplayActivity.this) .inflate(R.layout.block_canary_block_row, parent, false); } - TextView titleView = (TextView) convertView.findViewById(R.id.__leak_canary_row_text); - TextView timeView = (TextView) convertView.findViewById(R.id.__leak_canary_row_time); + TextView titleView = convertView.findViewById(R.id.__leak_canary_row_text); + TextView timeView = convertView.findViewById(R.id.__leak_canary_row_time); BlockInfoEx blockInfo = getItem(position); String index; @@ -360,7 +342,7 @@ public View getView(int position, View convertView, ViewGroup parent) { String keyStackString = BlockCanaryUtils.concernStackString(blockInfo); String title = index + keyStackString + " " + - getString(R.string.block_canary_class_has_blocked, blockInfo.timeCost); + getString(R.string.block_canary_class_has_blocked, Long.toString(blockInfo.timeCost)); titleView.setText(title); String time = DateUtils.formatDateTime(DisplayActivity.this, blockInfo.logFile.lastModified(), FORMAT_SHOW_TIME | FORMAT_SHOW_DATE); diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayConnectorView.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayConnectorView.java index 0f09d47..e07e9af 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayConnectorView.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayConnectorView.java @@ -53,7 +53,6 @@ public DisplayConnectorView(Context context, AttributeSet attrs) { type = Type.NODE; } - @SuppressWarnings("SuspiciousNameCombination") @Override protected void onDraw(Canvas canvas) { int width = getWidth(); diff --git a/blockcanary-android/src/main/res/values-v14/themes.xml b/blockcanary-android/src/main/res/values-v14/themes.xml deleted file mode 100644 index 0f875ae..0000000 --- a/blockcanary-android/src/main/res/values-v14/themes.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/blockcanary-sample/build.gradle b/blockcanary-sample/build.gradle index 32d69b8..4606b24 100644 --- a/blockcanary-sample/build.gradle +++ b/blockcanary-sample/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.application' android { compileSdkVersion LIBRARY_COMPILE_SDK_VERSION - buildToolsVersion LIBRARY_BUILD_TOOLS_VERSION defaultConfig { applicationId "com.example.blockcanary" @@ -14,16 +13,19 @@ android { buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + lintOptions { + checkAllWarnings true + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - debugCompile project(':blockcanary-android') - releaseCompile project(':blockcanary-android-no-op') + implementation fileTree(dir: 'libs', include: ['*.jar']) + debugImplementation project(':blockcanary-android') + releaseImplementation project(':blockcanary-android-no-op') - compile 'com.android.support:appcompat-v7:24.2.0' - compile 'com.android.support:design:24.2.0' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.material:material:1.0.0' } diff --git a/blockcanary-sample/src/main/AndroidManifest.xml b/blockcanary-sample/src/main/AndroidManifest.xml index fbf6d6b..ceac407 100644 --- a/blockcanary-sample/src/main/AndroidManifest.xml +++ b/blockcanary-sample/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + android:theme="@style/ModuThreeHandsomeTheme" + tools:ignore="AllowBackup,GoogleAppIndexingWarning"> + android:label="@string/app_name" + android:theme="@style/CjjBaseTheme"> diff --git a/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java b/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java index 612df72..3a0fdc8 100644 --- a/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java +++ b/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java @@ -15,11 +15,14 @@ */ package com.example.blockcanary; +import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.util.Log; import com.github.moduth.blockcanary.BlockCanaryContext; +import com.github.moduth.blockcanary.internal.BlockInfo; +import com.github.moduth.blockcanary.internal.NetUtils; import java.util.List; @@ -46,7 +49,7 @@ public String provideUid() { @Override public String provideNetworkType() { - return "4G"; + return NetUtils.getNetworkType(DemoApplication.getAppContext()) ; } @Override @@ -82,4 +85,14 @@ public List provideWhiteList() { public boolean stopWhenDebugging() { return true; } + + @Override + public void onBlock(Context context, BlockInfo blockInfo) { + super.onBlock(context, blockInfo); + Exception e = blockInfo.buildException(); + if(e != null){ + e.printStackTrace(); + } + Log.e("block",blockInfo.toString()); + } } \ No newline at end of file diff --git a/blockcanary-sample/src/main/java/com/example/blockcanary/DemoActivity.java b/blockcanary-sample/src/main/java/com/example/blockcanary/DemoActivity.java index 1c72795..958ae25 100644 --- a/blockcanary-sample/src/main/java/com/example/blockcanary/DemoActivity.java +++ b/blockcanary-sample/src/main/java/com/example/blockcanary/DemoActivity.java @@ -16,12 +16,10 @@ package com.example.blockcanary; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; -import android.view.View; public class DemoActivity extends AppCompatActivity { @@ -33,14 +31,6 @@ protected void onCreate(Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction() .add(R.id.container, DemoFragment.newInstance()) .commit(); - - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - showTipDialog(); - } - }); } private void showTipDialog() { @@ -65,8 +55,8 @@ public boolean onOptionsItemSelected(MenuItem item) { // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); - //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { + showTipDialog(); return true; } diff --git a/blockcanary-sample/src/main/java/com/example/blockcanary/DemoFragment.java b/blockcanary-sample/src/main/java/com/example/blockcanary/DemoFragment.java index 25b77ca..7a0a035 100644 --- a/blockcanary-sample/src/main/java/com/example/blockcanary/DemoFragment.java +++ b/blockcanary-sample/src/main/java/com/example/blockcanary/DemoFragment.java @@ -15,9 +15,11 @@ */ package com.example.blockcanary; +import android.os.Build; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -47,20 +49,17 @@ public View onCreateView(final LayoutInflater inflater, final ViewGroup containe } @Override - public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) { + public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - Button button1 = (Button) view.findViewById(R.id.button1); - Button button2 = (Button) view.findViewById(R.id.button2); - Button button3 = (Button) view.findViewById(R.id.button3); + Button button1 = view.findViewById(R.id.button1); + Button button2 = view.findViewById(R.id.button2); + Button button3 = view.findViewById(R.id.button3); + Button button4 = view.findViewById(R.id.button4); button1.setOnClickListener(this); button2.setOnClickListener(this); button3.setOnClickListener(this); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); + button4.setOnClickListener(this); } @Override @@ -80,14 +79,19 @@ public void onClick(View v) { } break; case R.id.button2: - for (int i = 0; i < 100; ++i) { - readFile(); + for (int i = 0; i < 200; ++i) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + readFile(); + } } break; case R.id.button3: double result = compute(); System.out.println(result); break; + case R.id.button4: + System.out.println("not implemented"); + break; default: break; } @@ -95,13 +99,14 @@ public void onClick(View v) { private static double compute() { double result = 0; - for (int i = 0; i < 1000000; ++i) { + for (int i = 0; i < 4000000; ++i) { result += Math.acos(Math.cos(i)); result -= Math.asin(Math.sin(i)); } return result; } + @Deprecated private static void readFile() { FileInputStream reader = null; try { diff --git a/blockcanary-sample/src/main/res/drawable-anydpi/ic_done.xml b/blockcanary-sample/src/main/res/drawable-anydpi/ic_done.xml new file mode 100644 index 0000000..49929f4 --- /dev/null +++ b/blockcanary-sample/src/main/res/drawable-anydpi/ic_done.xml @@ -0,0 +1,10 @@ + + + diff --git a/blockcanary-sample/src/main/res/drawable-hdpi/ic_done.png b/blockcanary-sample/src/main/res/drawable-hdpi/ic_done.png new file mode 100644 index 0000000..4c4b069 Binary files /dev/null and b/blockcanary-sample/src/main/res/drawable-hdpi/ic_done.png differ diff --git a/blockcanary-sample/src/main/res/drawable-mdpi/ic_done.png b/blockcanary-sample/src/main/res/drawable-mdpi/ic_done.png new file mode 100644 index 0000000..9883758 Binary files /dev/null and b/blockcanary-sample/src/main/res/drawable-mdpi/ic_done.png differ diff --git a/blockcanary-sample/src/main/res/drawable-xhdpi/ic_done.png b/blockcanary-sample/src/main/res/drawable-xhdpi/ic_done.png new file mode 100644 index 0000000..68e4365 Binary files /dev/null and b/blockcanary-sample/src/main/res/drawable-xhdpi/ic_done.png differ diff --git a/blockcanary-sample/src/main/res/drawable-xxhdpi/ic_done.png b/blockcanary-sample/src/main/res/drawable-xxhdpi/ic_done.png new file mode 100644 index 0000000..053ff40 Binary files /dev/null and b/blockcanary-sample/src/main/res/drawable-xxhdpi/ic_done.png differ diff --git a/blockcanary-sample/src/main/res/drawable/background_splash.xml b/blockcanary-sample/src/main/res/drawable/background_splash.xml deleted file mode 100644 index 8ecd5eb..0000000 --- a/blockcanary-sample/src/main/res/drawable/background_splash.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/drawable/btn_select.xml b/blockcanary-sample/src/main/res/drawable/btn_select.xml index a8a916a..588f1ba 100644 --- a/blockcanary-sample/src/main/res/drawable/btn_select.xml +++ b/blockcanary-sample/src/main/res/drawable/btn_select.xml @@ -1,8 +1,8 @@ - - - + + + \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/drawable/ic_done.png b/blockcanary-sample/src/main/res/drawable/ic_done.png deleted file mode 100644 index bf5bc7e..0000000 Binary files a/blockcanary-sample/src/main/res/drawable/ic_done.png and /dev/null differ diff --git a/blockcanary-sample/src/main/res/drawable/ic_launcher_foreground.xml b/blockcanary-sample/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..a5547a3 --- /dev/null +++ b/blockcanary-sample/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/blockcanary-sample/src/main/res/layout/activity_demo.xml b/blockcanary-sample/src/main/res/layout/activity_demo.xml index 066c36a..0b423d5 100644 --- a/blockcanary-sample/src/main/res/layout/activity_demo.xml +++ b/blockcanary-sample/src/main/res/layout/activity_demo.xml @@ -19,13 +19,4 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="MergeRootFrame" /> - - \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/layout/activity_main.xml b/blockcanary-sample/src/main/res/layout/activity_main.xml index 5c5fdff..d5dabb8 100644 --- a/blockcanary-sample/src/main/res/layout/activity_main.xml +++ b/blockcanary-sample/src/main/res/layout/activity_main.xml @@ -7,24 +7,23 @@ + android:background="@color/material_blue" + android:visibility="gone"> + android:textSize="18sp" /> @@ -94,14 +93,4 @@ - - - \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/menu/menu_demo.xml b/blockcanary-sample/src/main/res/menu/menu_demo.xml index 300f66a..f841b74 100644 --- a/blockcanary-sample/src/main/res/menu/menu_demo.xml +++ b/blockcanary-sample/src/main/res/menu/menu_demo.xml @@ -1,5 +1,10 @@ - - + + \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/blockcanary-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/blockcanary-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/blockcanary-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/blockcanary-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/mipmap-hdpi/ic_launcher.png b/blockcanary-sample/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..fb04068 Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/blockcanary-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..fb04068 Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-mdpi/ic_launcher.png b/blockcanary-sample/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..4265ffb Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/blockcanary-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..4265ffb Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/blockcanary-sample/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..d8ea51c Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/blockcanary-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ea51c Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png index 16854f6..2a3e83d 100644 Binary files a/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..2a3e83d Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/blockcanary-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..7d6b1dd Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/blockcanary-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/blockcanary-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..7d6b1dd Binary files /dev/null and b/blockcanary-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/blockcanary-sample/src/main/res/values/dimens.xml b/blockcanary-sample/src/main/res/values/dimens.xml index ad34f6b..73a8f4d 100644 --- a/blockcanary-sample/src/main/res/values/dimens.xml +++ b/blockcanary-sample/src/main/res/values/dimens.xml @@ -1,10 +1,4 @@ - - 16dp - 16dp - 0dp 48dp - 48dp - 0.5dp diff --git a/blockcanary-sample/src/main/res/values/ic_launcher_background.xml b/blockcanary-sample/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/blockcanary-sample/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/blockcanary-sample/src/main/res/values/styles.xml b/blockcanary-sample/src/main/res/values/styles.xml index 5e0dd50..b309e57 100644 --- a/blockcanary-sample/src/main/res/values/styles.xml +++ b/blockcanary-sample/src/main/res/values/styles.xml @@ -3,11 +3,10 @@ - diff --git a/build.gradle b/build.gradle index 2e498be..f3e8219 100644 --- a/build.gradle +++ b/build.gradle @@ -4,21 +4,32 @@ buildscript { repositories { mavenCentral() jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.android.tools.build:gradle:3.5.0' } } allprojects { repositories { + maven { url 'https://jitpack.io' } mavenCentral() jcenter() + google() } ext { - LIBRARY_COMPILE_SDK_VERSION = 23 - LIBRARY_BUILD_TOOLS_VERSION = "23.0.3" - LIBRARY_MIN_SDK_VERSION = 9 - LIBRARY_TARGET_SDK_VERSION = 22 + LIBRARY_COMPILE_SDK_VERSION = 29 + LIBRARY_MIN_SDK_VERSION = 16 + LIBRARY_TARGET_SDK_VERSION = 29 } + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:deprecation" + } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir } diff --git a/gradle.properties b/gradle.properties index d4b7bce..2eab12f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,21 @@ -## Project-wide Gradle settings. -# +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html -# + # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -# +org.gradle.jvmargs=-Xmx8192M + # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -#Sat Mar 05 00:07:08 CST 2016 -org.gradle.jvmargs=-Xmx8192M -#org.gradle.jvmargs=-Xmx10248m -XX\:MaxPermSize\=512m -XX\:+HeapDumpOnOutOfMemoryError -Dfile.encoding\=UTF-8 -org.gradle.daemon=true -org.gradle.configureondemand=true org.gradle.parallel=true -android.useDeprecatedNdk=true \ No newline at end of file +org.gradle.daemon=true +org.gradle.configureondemand=false +android.useAndroidX=true +android.enableJetifier=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2322723..5c2d1cf 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 586936a..f4d7b2b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Apr 13 16:42:11 CST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/gradlew b/gradlew index 9d82f78..b0d6d0a 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,20 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## ## @@ -6,20 +22,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +75,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +105,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +170,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..15e1ee3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,100 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega