例如,5.0以上才有的查看应用使用情况的api,在某个类中,我们先
import android.app.usage.UsageEvents.Event;
然后有个方法
public static List<UsageStats> getUsageStatsList(Context context) {
List<UsageStats> usageStatsList = null;
try {
UsageStatsManager usm = getUsageStatsManager(context);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, -1);
long startTime = calendar.getTimeInMillis();
usageStatsList = usm.queryUsageStats(
UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
} catch (Exception ex) {
}
return usageStatsList;
}
这个apk用api 22编译通过,打包成apk,没问题。
然后在5.0以上手机运行,没问题。
如果子5.0以下的,比如4.2.2手机上
-
一开始,ClassLoader载入这个class,发现了一个当前没有的东西,dalvikvm就会警告【注意是警告,warning,不是error,因此不会崩溃】找不到类或者方法,NoSuchMethodError or ClassNotFoundException
-
如果你没有判断api level就直接执行上述方法,那么就会报错,这个时候就是Exception了,导致应用程序崩溃。这个时候的处理办法其实很多人都知道,就是判断Build.VERSION.SDK_INT >= 21之后再调用方法
其实我想有些人可能跟我之前想法一样,认为载入class
的时候,【执行import
语句发现没有对应api
就报错】,其实这是下意识的这么认为,仔细想想java class的构造
,或者看看简单smali
文件,就应该知道,其实class中根本就没有所谓的import语句,这个只是方便用户编写的,真正class中的,都是绝对路径
。
看个简单例子(不知道哪儿的一个被我曾反编译过的):
.class final Lcom/flurry/android/a;
.super Ljava/lang/Object;
.source "SourceFile"
# instance fields
.field a:Ljava/lang/String;
.field b:J
.field c:Ljava/lang/String;
.field d:Ljava/lang/String;
.field e:Landroid/os/Handler;
# direct methods
.method constructor <init>()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
所以说,根本不会出现什么执行import语句导致找不到类报错的现象(Eclipse作为IDE只是根据编译版本来拒绝你编译而已)。
在IDE中import了一个新版本的api,eclipse报错了,没关系,把编译的android target调整为对应api版本就行,Eclipse中是修改project.properties将里面的target一栏改下,比如上面的5.0以上才有的api, 刚开始我用的target 19会提示报错,改为 target=android-22 就可以了,然后注意在真正调用的地方处理好SDK_INT判断逻辑即可。
评论区