Android API兼容,其他API,UI适配(2)

- Gson、FastJson、org.JSON到底哪一个效率更高,速度更快- https://blog.csdn.net/zml_2015/article/details/52165317

-- Try catch与throw new Exception的区别?
 Try catch可以捕获住异常,不让程序崩溃;
 throw new Exception 与 throws Exception抛出异常,不去处理,会导致程序崩溃。
抛出异常,程序会崩溃吗,会的。

-- WifiP2pManager 4.0,使用WiFi P2P需要Android API Level >= 14才可以;
SDK4.1对应API 16;
 Android 4.1API WifiManager新特性;
 WifiP2P是在 Android 4.0 以上系统中加入的功能,通过WifiP2P可以在不连接网络的情况下,直接与配对的设备进行数据交换。他相比蓝牙传输速率更快,更远;相比网络传输过程中不会消耗流量。WifiP2P的传输依赖于无限WiFi,因此设备之间通信需要连接同一个WiFi网络。在WifiP2P技术中有一个核心类WifiP2pManager,他提供了所有的通信相关的广播信息,监听信息,设备信息以及初始化操作等。在信息传输过程中需要有个接收端接收信息和发送端发送信息,这里称为客户端和服务端,客户端和服务端通过WifiP2P作为传输手段,通过socket作为信息载体,进行通信。

https://www.jianshu.com/p/14ec886bb624
android wifi 点对点传输- https://github.com/changchengfeng/WifiP2PSample
Wi-Fi DirectAPI在Android 4.1中被增强以支持在WifiP2pManager中的预先关联服务发现。这允许在连接之前使用Wi-Fi Direct通过服务发现和筛选周围的设备。与此同时,Network ServiceDiscovery允许你在一个已存在并保持连接的网络上发现一个服务(例如一个本地的Wi-Fi网络)。

-- 解决Android ImageView用setImageDrawable方法图片缩小的问题-https://blog.csdn.net/changemyself/article/details/43054933

- setImageDrawable(getResources().getDrawable()但是发现在5.1中是过期的
Android中getResources().getDrawable() 过时的解决方法-https://blog.csdn.net/xu20082100226/article/details/72625266
 1.当你这个Drawable不受主题影响时
ResourcesCompat.getDrawable(getResources(), R.drawable.name, null);
 2.当你这个Drawable受当前Activity主题的影响时
ContextCompat.getDrawable(getActivity(), R.drawable.name);
 3.当你这个Drawable想使用另外一个主题样式时
ResourcesCompat.getDrawable(getResources(), R.drawable.name, anotherTheme);

Android中图片setImageResource和setBackgroundResource的区别
 刚好项目中碰到需要再一个button点击的时候进行图片的切换, 很简单的实现了,但是呢,之前使是iv_setBackgroundResource的方法来设置背景图片的切换,因为之前都是这么干的,可是这个翻水水了,会出现背景图片重叠阴影的问题,后面使用了setImageResource,直接去设置图片的资源路径就显示正常了。原因是现在的图片是带有阴影的背景的,所以设置setBackground会出现问题。
 
在代码中为ImageView引用图片之setImageDrawable和setBackgroundResource- https://blog.csdn.net/languobeibei/article/details/69389153

- 关于Java中null的十点详解- https://www.cnblogs.com/greatfish/p/5906617.html
String str = null;
str = str+"hello";
打印结果为:null hello

-- TaskStackBuilder  API level16(4.1);4.0对应API是:14.
关于TaskStackBuilder- https://www.cnblogs.com/aheiabai/p/5931536.html
TaskStackBuilder  API level16(4.1)
TaskStackBuilder可以构造一个合成的回退栈,主要用于跨任务导航,应用于Android3.0及新版本。
  我们通常利用返回键导航app,而返回键是基于当前任务的导航,这种局部的导航只有将当前任务中所有Activity结束掉时才返回上个任务,若从当前app跳转到另一app时就涉及到不同任务的跳转,也就是从任务一跳转到任务二时,从任务二中按返回键时无法直接返回到任务一,除非任务二中只存在一个Activity。
  为了提供更好的用户体验,在跨应用的跳转中,利用TaskStackBuilder的getPendingIntent(int requestCode, int flags),可将当前任务中的Activity和要启动的Activity合成为一个新的任务,而用户按返回键的操作就作用在这个新任务中,这相当于实现了跨任务直接跳转。
  若从任务一直接启动一个Intent去开启另一个应用的Activity,会直接把该Activity加入到这个应用的任务二中去,按返回键时最终只会回到主界面,而不会回到任务一。

若要向老版本兼容可使用android.support.v4.app.TaskStackBuilder实现相同效果。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            TaskStackBuilder stackBuilder = TaskStackBuilder.create(mActivity);
            stackBuilder.addParentStack(CarActivity.class);
            stackBuilder.addNextIntent(intent);
            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
                    PendingIntent.FLAG_UPDATE_CURRENT);

            builder.setContentIntent(resultPendingIntent);

            NotificationManager notificationManager = (NotificationManager) mActivity
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            Notification n = builder.build();
            n.flags = n.flags | Notification.FLAG_AUTO_CANCEL;
            notificationManager.notify(notificationFinished, n);
        } else {
            android.support.v4.app.TaskStackBuilder stackBuilder = android.support.v4.app.TaskStackBuilder.create(mActivity);
            stackBuilder.addParentStack(CarActivity.class);
            stackBuilder.addNextIntent(intent);
            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
                    PendingIntent.FLAG_UPDATE_CURRENT);

            builder.setContentIntent(resultPendingIntent);

            NotificationManager notificationManager = (NotificationManager) mActivity
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            Notification n = builder.build();
            n.flags = n.flags | Notification.FLAG_AUTO_CANCEL;
            notificationManager.notify(notificationFinished, n);
        }

private static long getTotalSize(String path) {
        StatFs fileStats = new StatFs(path);
        fileStats.restat(path);
        if (Build.VERSION.SDK_INT >= 18) {
            return (long) fileStats.getBlockCountLong() * fileStats.getBlockSizeLong();
        } else {
            return (long) fileStats.getBlockCount() * fileStats.getBlockSize();
        }
    }

Canvas.saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags):

本身和save方法差不多,但是它单独分配了一个画布用于绘制图层。它定义了一个画布区域(可设置透明度),此方法之后的所有绘制都在此区域中绘制,直到调用canvas.restore()方法。例如:在调用saveLayerAlpha方法之前绘制了一个“圆形”,在调用saveLayerAlpha方法之后绘制了一个“圆形”此时这两个圆形并不在同一个图层。下面给出一个例子以及样图来说明这个问题。

-- Thread.run(),start()
    调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void.。
 
  Thread的run()与start()的区别- https://blog.csdn.net/qiumeng_1314/article/details/79466655
 1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。 
  用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
 2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
  run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。

public class Test {  
    public static void main(String[] args) {  
        Runner1 runner1 = new Runner1();  
        Runner2 runner2 = new Runner2();  
//      Thread(Runnable target) 分配新的 Thread 对象。  
        Thread thread1 = new Thread(runner1);  
        Thread thread2 = new Thread(runner2);  
//      thread1.start();  
//      thread2.start();  
        thread1.run();  
        thread2.run();  
    }  
}  
class Runner1 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程  
    public void run() {  
        for (int i = 0; i < 100; i++) {  
            System.out.println("进入Runner1运行状态——————————" + i);  
        }  
    }  
}  
class Runner2 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程  
    public void run() {  
        for (int i = 0; i < 100; i++) {  
            System.out.println("进入Runner2运行状态==========" + i);  
        }  
    }  
}  

-- 提供的SwitchButton-https://github.com/kyleduo/SwitchButton

-- canvas.saveLayerAlpha
// canvas.saveLayerAlpha(RectF bounds, int alpha, int saveFlags) 在API26被废弃,Canvas下Flag常量在API27
//   canvas.saveLayerAlpha(mSaveLayerRectF, mAlpha, Canvas.MATRIX_SAVE_FLAG
//                | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
//                | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
        canvas.saveLayerAlpha ( mSaveLayerRectF , mAlpha );


View.setBackground上下版本兼容型的问题
int sdk = android.os.Build.VERSION.SDK_INT;
        if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setBackgroundDrawable( drawable );
        }
        else {
            setBackground( drawable );
        }

if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
                    setBackgroundDrawable( null );
                }
                else {
                    setBackground( null );
                }

LeftBtn.setBackground(ContextCompat.getDrawable(mActivity, R.drawable.guide_btn_prev_prss));

-- RenderScript; ScriptIntrinsicBlur sdk4.2
AndroidStudio中使用V8包中的RenderScript,只需要修改项目的build.gradle中的代码即可
对于android gradle plugin v0.14+:
android {
    ...
    defaultConfig {
        ...
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }
    ...
}
在android gradle plugin v0.13.3及以前的版本中:
android {
        ...
        defaultConfig {
            ...
            renderscriptTargetApi 19
            renderscriptSupportMode true
        }
        ...
    }
之后,我们就可以在2.2以上的代码中使用v8包中的RenderScript了,如:
import android.support.v8.renderscript.*

 android.renderscript.ScriptIntrinsicBlur 4.2导致这个问题就是因为这个api不能向下兼容,现在我们就来解决这个问题。其实google早就提供了方案,我们只需要使用就好了。
1、引入renderscript-v8.jar(将jar包放在libs目录下,add to build path)

-- Android 8.0 利用Settings.Global属性跨应用定义标志位-https://blog.csdn.net/ouzhuangzhuang/article/details/82258148
  系统级别应用
在需要定义的地方使用 SystemProperties.set(“dev.xxx.xxx”, “false”);
在获取的部分使用 SystemProperties.getBoolean(“ro.mmitest”, false))
最后记得要导包 import android.os.SystemProperties
  非系统级别应用
在需要定义的地方使用 Settings.Global.putInt(context.getContentResolver(),“xxx.xxx”,1);
在获取的部分使用 boolean mTag = Settings.Global.getInt(getActivity().getContentResolver(),“xxx.xxx”, 0) == 1;
依旧别忘记导包 import android.provider.Settings;

Android实践 -- 设置系统日期时间和时区-https://www.jianshu.com/p/6c6a6091545d
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>

--适配未知来源的管理权限,手机兼容刘海屏解决方案
关于Android各个类型手机兼容刘海屏解决方案- https://blog.csdn.net/mr_zengkun/article/details/80984117
Android中系统应用适配未知来源的管理权限-https://blog.csdn.net/zdc9023/article/details/78861822
Android中为了防止一些不良应用的随便静默安装,设置了未知来源应用的开关,在不同的android版本中使上会有所区别
/**
     * 打开未知来源权限
     * @param context
     */
    public static void openNonMarketAppsPerm(Context context){
        if (Build.VERSION.SDK_INT < 17) {
            int flag = Settings.Secure.getInt(context.getContentResolver(),
                    Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
            if(flag == 0){
                Settings.Secure.putInt(context.getContentResolver(),
                        Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
            }
        } else {
            int flag = Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.INSTALL_NON_MARKET_APPS, 0);
            if(flag == 0){
                Settings.Global.putInt(context.getContentResolver(),
                        Settings.Global.INSTALL_NON_MARKET_APPS, 1);
            }
        }
    }
 /**
     * 关闭未知来源权限
     * @param context
     */
    public static void closeNonMarketAppsPerm(Context context){
        if (Build.VERSION.SDK_INT < 17) {
            int flag = Settings.Secure.getInt(context.getContentResolver(),
                    Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
            if(flag == 1) {
                Settings.Secure.putInt(context.getContentResolver(),
                        Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
            }
        } else {
            int flag= Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.INSTALL_NON_MARKET_APPS, 1);
            if (flag==1){
                Settings.Global.putInt(context.getContentResolver(),
                        Settings.Global.INSTALL_NON_MARKET_APPS, 0);
            }
        }
    }

    /**
     * 检查状态是否打开
     * @param context
     */
    public static boolean checkNonMarketAppsPermStatus(Context context){
        boolean unKnowSource=false;
        if (Build.VERSION.SDK_INT<17){
            unKnowSource=Settings.Secure.getInt(context.getContentResolver(),
                    Settings.Secure.INSTALL_NON_MARKET_APPS, 0)==1;
        }else{
            unKnowSource=Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.INSTALL_NON_MARKET_APPS, 0)==1;
        }
        return unKnowSource;
    }
 如果兼容4.0以下版本则需要把Settings.Secure 和Settings.Global 改为:Settings.System方式获取未知来源的状态或修改状态

- wait(),notify/notifyAll
 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。
 当执行notify/notifyAll方法时,会唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。
 

猜你喜欢

转载自blog.csdn.net/ShareUs/article/details/85060062
今日推荐