# 问题解决

解决java.lang.RuntimeException: Unable to start activity Activity无法打开的问题

在跑一个Android project时,出现以下错误:

/************************************************************/

FATAL EXCEPTION: main Process: com.example.leidong.myapp, PID: 4506 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.leidong.myapp/com.example.leidong.myapp.loginAndRegister.UserRegister}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

/***********************************************************/

大概主要的意思是说没法打开UserRegister这个Activity。

因此app直接没法运行,虚拟机上提示的是“Unfortunately MyAPP has stoped”。注意,此时我的AndroidManifest.xml已经声明了UserRegister的Activity,整个src代码和res中也不报任何错误。

解决办法

看下UserRegister.java,发现UserRegister类继承的是ActionBarActivity类而不是Activity类,于是把继承的ActionBarActivity类改成Activity类,之后再跑app,发现问题得到解决,app可以正常调试。截图见下:

@SuppressLint(“HandlerLeak”)

碰到方法的前面和类的前面有时会出现@SuppressLint或者@SuppressWarnings这样的黄色警告,看起来很不舒服,于是上网搜集了一些相关资料。发现这些警告的出现其实是由于我们编写代码时的一些不规范的写法导致,解决这些问题其实是能提高我们程序的安全性、可用性和性能的。接下来就让我为大家一一说明。 

1、@SuppressLint(“DrawAllocation”) 

  • 原因:我们都知道View及其子类的OnDraw(Canvas canvas)方法会实时调用来更新界面的,然而有时我们会在onDraw(Canvas canvas)方法中实例化对象(如Paint paint=new Paint()),这样就会影响我们程序的效率。 
  • 解决办法:将这些对象改为类的成员变量。

2、@SuppressWarnings(“rawtypes”)和@SuppressWarnings({ “unchecked”, “rawtypes” }) 

  • 不规范写法:
Class clazz = Class.forName(“android.view.Display”); 
  • 正确写法:
Class<?> clazz = Class.forName("android.view.Display");

3、@SuppressLint(“HandlerLeak”) 

  • 原因:Handler在Android中用于消息的发送与异步处理,常常在Activity中作为一个匿名内部类来定义,此时Handler会隐式地持有一个外部类对象(通常是一个Activity)的引用。当Activity已经被用户关闭时,由于Handler持有Activity的引用造成Activity无法被GC回收,这样容易造成内存泄露。 
  • 解决办法:将其定义成一个静态内部类(此时不会持有外部类对象的引用),在构造方法中传入Activity并对Activity对象增加一个弱引用,这样Activity被用户关闭之后,即便异步消息还未处理完毕,Activity也能够被GC回收,从而避免了内存泄露。
public static class MyHandler extends Handler {
        private WeakReference<Activity> reference
        public MyHandler(Activity activity) {
            reference = new WeakReference<Activity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            if (reference.get() != null) {
                switch (msg.what) {
                case 0:
                    // do something...
                    break;
                default:
                    // do something...
                    break;
                }
            }
        }

静态内部类实现,据说这是最标准的写法。

private MyHandler handler = new MyHandler(this);
    static class MyHandler extends Handler {
        WeakReference weakReference;
        public MyHandler(SecondActivity activity) {
            weakReference = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {

        }
    }
  • 另一种情况:
  • 不规范的写法:
private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

        };
    };
  • 正确的写法:
private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            return false;
        }
    });    

4、@SuppressLint(“SimpleDateFormat”) 

  • 不规范写法:
 SimpleDateFormat format = new SimpleDateFormat(pattern); 
 ```
* 正确写法:
```java
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault());

5、@SuppressLint(“DefaultLocale”) 

  • 不规范写法:String lower = string.toLowerCase(); 
    boolean b = “String”.toUpperCase().equals(“STRING”); 
  • 正确写法:
String lower = string.toLowerCase(Locale.getDefault()); 
boolean b = “String”.toUpperCase().equals(“STRING”);

6.解决重写onTouch事件提示的警告

【我的Android进阶之旅】解决重写onTouch事件提示的警告:onTouch should call View#performClick when a click is detected

OnTouch关于performClick的Warning

7.androidstudio support包报错 add google maven respository and sync project

解决:处理

8.更新Android studio, build报错:ParseError at [row,col]:[28,9] Message: expected start or end tag

解决:存在非xml的语法,注意检查语法错误

9.This Handler class should be static or leaks might occur (anonymous android.os.Handler) less… (Ctr

解决:处理

10.Android 9.0 https适配问题

描述:在Android9.0中,谷歌要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。
为了继续在使用http协议,那么要么是降低targetSdkVersion版本,要么使用一下方法:

1.在 res 下新增一个 xml 目录,然后创建一个名为:network_security_config.xml 文件(名字自定) ,内容如下,大概意思就是允许开启http请求

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

然后在APP的AndroidManifest.xml文件下的application标签增加以下属性

<application
...
 android:networkSecurityConfig="@xml/network_security_config"
...
/>

最后我建议还是将协议改成https,毕竟https比http安全的多,而且iOS早就要求开发者使用https,小程序中更是只能使用https。

11.android 通过包名启动其他app并打开指定的页面

public static Intent getAppOpenIntentByPackageName(Context context,String packageName){
    //Activity完整名
    String mainAct = null;
    //根据包名寻找
    PackageManager pkgMag = context.getPackageManager();
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED|Intent.FLAG_ACTIVITY_NEW_TASK);


    @SuppressLint("WrongConstant") List<ResolveInfo> list = pkgMag.queryIntentActivities(intent,
            PackageManager.GET_ACTIVITIES);
    for (int i = 0; i < list.size(); i++) {
        ResolveInfo info = list.get(i);
        if (info.activityInfo.packageName.equals(packageName)) {
            mainAct = info.activityInfo.name;
            break;
        }
    }
    if (TextUtils.isEmpty(mainAct)) {
        return null;
    }
    intent.setComponent(new ComponentName(packageName, mainAct));
    return intent;
}

public static Context getPackageContext(Context context, String packageName) {
    Context pkgContext = null;
    if (context.getPackageName().equals(packageName)) {
        pkgContext = context;
    } else {
        // 创建第三方应用的上下文环境
        try {
            pkgContext = context.createPackageContext(packageName,
                    Context.CONTEXT_IGNORE_SECURITY
                            | Context.CONTEXT_INCLUDE_CODE);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
    return pkgContext;
}

public static boolean openPackage(Context context, String packageName) {
    Context pkgContext = getPackageContext(context, packageName);
    Intent intent = getAppOpenIntentByPackageName(context, packageName);
    if (pkgContext != null && intent != null) {
        intent.putExtra("openMoudle","serviceHall");
        pkgContext.startActivity(intent);
        return true;
    }
    return false;
}
private boolean checkPackInfo(String packname) {
    PackageInfo packageInfo = null;
    try {
        packageInfo = getPackageManager().getPackageInfo(packname, 0);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return packageInfo != null;
}
 

在oncreate方法里调用

if (checkPackInfo("com.bonc.mobile.unicom.jl.richwin")) {
    openPackage(MainActivity.this,"com.bonc.mobile.unicom.jl.richwin");
} else {
    Toast.makeText(MainActivity.this, "没有安装" + "",Toast.LENGTH_LONG).show();
    //TODO  下载操作
}

Android中常见的内存泄露及解决办法汇总

Android中常见的内存泄露及解决办法汇总

Android 沉浸式状态栏完美解决方案

Android 沉浸式状态栏完美解决方案

分类: Android

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注