存儲沙箱化, 每一個應用訪問本身沙箱內的文件。訪問別的沙箱解決辦法相似於FileUriExposedException,用FileProvider將file轉換爲content傳遞java
設備惟一id獲取,谷歌開放了新的設備id獲取方式,目前不一樣手機獲取的方式不一樣之前的 READ_PHONE_STATE
方式變爲了READ_PRIVILEGED_PHONE_STATE
android
非SDK接口的限制,設置禁止對非sdk接口的依賴,主要是一些第三方的熱修復,加固方案使用了這些被限制的SDK接口git
限制了明文流量,只有使用https才能夠訪問github
Android 6.0(M) ,完整的權限控制,危險權限須要動態獲取。 API 檢測是否有受權,申請受權,權限失敗解釋面試
Android7.0 (N) , 刪除了三種靜態廣播 網絡狀態新照片和新視頻算法
Android8.0(P),自適應的圖標類型,推送和通知的管理數據庫
Retrofit使用Retrofit.create(Class)
方法建立出Service 接口對象,使retrofit能夠在Service中進行參數配置編程
然而在Retrofit.create()
方法中,是使用Proxy.newProxyInstance()
方法來建立Service接口實例,這個實例實現了全部的接口方法,調用實例的InvocationHandler
成員變量的invoke()
方法,InvocationHandler
對象就會代理接口中的是設定。設計模式
invoke()
中的邏輯:api
loadServiceMethod(method)
將interface中的方法信息讀取並初步分析生成ServiceMethod
OkHttpCall<Object> okHttpCall = new OkhttpCall<>(serviceMethod,args)
負責將ServiceMethod封裝到retrofit2.call
對象,該對象在enqueue等的時候會調用okhttp.call
對象,由它來進行網絡請求的發起
在serviceMethod.adapt(okHttpCall)
中,serviceMethod裏面的的callAdapter對象把okHttpCall
轉爲新的retrofit.call
類型對象。這個call中,後臺線程發起的請求的返回中,調用主線程回調方法。還能夠生成rxjava的Obervable等
首先創造出一個OkhttpClient進行網絡配置,而後建立一個Request傳入client,client建立一個call開始發起請求。
Dispatcher dispatcher
:調度器,調度後臺發起的網絡請求,可設置主機請求數和後臺請求數
List<Protocol> protocols
:支持的應用層協議版本
List<ConnectionSpec> connectionSpecs
:應用層支持的Socket設置,即便用明文傳輸 仍是TLS
List<Interceptor> interceptors
大多數的Interceptor都會配置在這裏
List<Interceptor> networkInterceptors
:直接和網絡請求交互的Interceptor配置到這裏
CookieJar cookieJar
:管理Cookie的控制器,提供了基礎的存取判斷,剩下的須要本身實現
Cache cache
:Cache 存儲的配置。默認是沒有,若是須要⽤,得⾃⼰配置出 Cache 存儲的⽂件位置以及存儲空間上限。
HostnameVerifier hostnameVerifier
:⽤於驗證 HTTPS 握⼿過程當中下載到的證書所屬者是否和⾃⼰要訪問的主機名⼀致。
Authenticator[ɔːˈθɛntɪkeɪtə] authenticator
:用於自動從新認證。配置後收到401時會直接調用authenticator,從新發起請求
OKHttp3經過攔截鏈的設計,讓請求分紅5個攔截器去處理,攔截器各司其職,擴展性很是高。攔截鏈是從自定義的攔截器開始,而後再到默認的5個攔截器。通常狀況下咱們想打印網絡請求日誌,因此能夠自定義Log攔截器,若是要給全部請求添加Header,一樣能夠自定義Header攔截器。
步驟: 步驟一:主線程匿名內部類建立Handler對象 步驟二:建立消息對象 經過Message message=Message.obtain()
建立一個message 步驟三:發送消息mHandler.sendMessage(msg);
UI線程建立一個Handler對象,而後在子線程中sendMessage發送到在主線程的MessageQueue中,最後經過Lopper(消息泵)對象去除MessageQueue中的消息,分發回Handler的handleMessage()
中
線程池用於線程的調度、複用;handler用於異步通訊
內部有一個SerialExecutor任務隊列線程池(任務調度)
和THREAD_POOL_EXECUTOR執行線程池(真正執行任務的線程池)
和內部handler(異步通訊+消息傳遞)
,
AsynTask屬於抽象類需實現子類 execute(Params... params)
:觸發執行異步線程任務,必需在UI線程中調用 onPreExecute()
:執行線程任務前的操做執行任務前調用,如顯示進度條等操做 doInBackground(Params params)
:接受輸入參數,執行任務中的耗時操做,返回執行結果。 onPostExecute(Resule result)
:接收線程任務執行結果,顯示到UI組件 onCancelled
:將異步任務設置爲取消狀態,doInBackground()
中判斷終止任務 點擊查看AsynTask原理具體說明
同步鎖修飾execute()
從而保證AsyncTask中的任務是串行執行的
首先用戶觸摸View層(好比控件xml啥的都算view)
Controller層(Activity,Fragment)
作出反應去請求 Model層(http, 數據庫,sp)
的數據,而後返回數據給C層,C層收到數據後通知View層進行更新
首先用戶觸摸View層(Activity,Fragment)
如點擊請求網絡 而後view層調用Presenter(橋樑層)
層去Model層(網絡請求數據,數據庫數據,sp數據,contentProvider)
拿對應的數據 最後P層經過初始化時持有的View層引用將view的更新通知給V層
將app拆分紅不少塊,每一個模塊都是一個apk,最終打包的時候講宿主apk和插件apk分開打包,插件apk經過動態下發到宿主apk。 用的是VirtualAPK
1.宿主Module中的build.gradle中添加配置,apply plugin
2.application中進行初始化 3.適當位置加載插件
PluginManager pluginManager = PluginManager.getInstance(base);
File apk = new File(Environment.getExternalStorageDirectory(), "plugin.apk");
if (apk.exists()) {
try {
pluginManager.loadPlugin(apk);
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(),"SDcard根目錄未檢測到plugin.apk插件", Toast.LENGTH_SHORT).show();
}
複製代碼
4.加載插件
public void click(View view){
Intent intent = new Intent();
intent.setClassName("com.emm.plugin","com.emm.plugin.Main2Activity");
tartActivity(intent);
}
複製代碼
原生apk就可做爲插件加載,插件工程編譯生成apk後,便可經過宿主app加載,並在宿主中建立LoadedPlugin對象。再次啓動就會變得流暢 插件apk須要在宿主Apk中提早佔坑,經過Hook Activity的啓動過程,「欺上瞞下」啓動插件Apk中的Activity,其餘三大組件都是經過代理的方式。
應用層 HTTP 、FTP 傳輸層 TCP、UDP 網絡層 IP、ICMP、ARP 數據鏈路層 FDDI、IEEE 802.1A
Cookie是由服務器端生成,服務器須要客戶端保存的內容,放在Set-Cookie
headers裏返回,客戶端會自動保存 客戶端保存的Cookie會在以後的全部請求裏攜帶進Cookie
header裏發回給服務器 客戶端保存Cookie是按照服務器域名來分類的
簡單的說就是Cookies追蹤,利用第三方cookie來實現這一的機制 不少第三方做爲跨域提供了用戶的token
工廠模式:寶馬和奔馳類都實現car接口,用CarFactory
返回實例化接口car,至關於一個工廠能夠生產不一樣類型的實例 模板模式:抽象模板角色類,實現了父類所聲明的基本方法。子類實現須要強制實現的邏輯 觀察者模式: 1.抽象被觀察者接口,聲明添加通知刪除觀察者方法
public interface Observerable {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
複製代碼
2.定義一個抽象觀察者接口
public interface Observer {
public void update(String message);
}
複製代碼
3.定義被觀察者,實現了Observerable接口,對接口方法進行了具體實現
public class WechatServer implements Observerable {
//注意到這個List集合的泛型參數爲Observer接口,設計原則:面向接口編程而不是面向實現編程
private List<Observer> list;
private String message;
public WechatServer() {
list = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
if(!list.isEmpty())
list.remove(o);
}
//遍歷
@Override
public void notifyObserver() {
for(int i = 0; i < list.size(); i++) {
Observer oserver = list.get(i);
oserver.update(message);
}
}
public void setInfomation(String s) {
this.message = s;
System.out.println("微信服務更新消息: " + s);
//消息更新,通知全部觀察者
notifyObserver();
}
}
複製代碼
4.定義具體觀察者,微信公衆號具體觀察者爲用戶User
public class User implements Observer {
private String name;
private String message;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + " 收到推送消息: " + message);
}
}
複製代碼
5.編寫一個測試類,首先註冊了三個用戶,ZhangSan、LiSi、WangWu。公衆號發佈了一條消息"PHP是世界上最好用的語言!",三個用戶都收到了消息。 用戶ZhangSan看到消息後頗爲震驚,果斷取消訂閱,這時公衆號又推送了一條消息,此時用戶ZhangSan已經收不到消息,其餘用戶
public class Test {
public static void main(String[] args) {
WechatServer server = new WechatServer();
Observer userZhang = new User("ZhangSan");
Observer userLi = new User("LiSi");
Observer userWang = new User("WangWu");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的語言!");
System.out.println("----------------------------------------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的語言!");
}
}
複製代碼
適配器模式:
ViewStub:寬高都爲 0 的不可見 View. 經過延遲加載佈局的方式優化佈局提高渲染性能,經過setVisibility或者直接調用inflate都會渲染布局文件 ViewPager2:核心爲RecyclerView
+LinerLayoutManager
,因此支持橫向和豎向的滾動,viewpager2
能夠承載fragment,須要繼承它提供的FragmentStateAdapter
,還能夠完整支持notifyDataSetChanged()
CoordinatorLayout: 1.CoordinatorLayout繼承自viewgroup,可是使用相似於framLayout,只有CoordinatorLayout的直接子佈局才能響應。 2.是須要CoordinateLayout
+AppBarLayout
+CollapingToolbarLayout
結合纔有效果。
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="15dp"
android:src="@drawable/add_2"/>
</android.support.design.widget.CoordinatorLayout>
複製代碼
scroll|exitUntilCollapsed
,子控件能夠向上滾動出NestedScrollView父佈局時會摺疊到頂端scroll|enterAlways
:只要向下滾動該佈局就會顯示出來,向上滾動該佈局就會收縮scroll|enterAlwaysCollapsed
:向下滾動到最低端時,該佈局纔會顯示出來使用CMake
進行ndk開發,它是一種比nake更高級的編譯配置工具,經過CMakeLists.txt,能夠控制生成的Makefile,從而控制編譯過程、生成源碼包、生成當前平臺安裝包。
.h
文件.so
文件PercentRelativeLayout
、PercentFrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ff0000"
app:layout_heightPercent="30%"
app:layout_widthPercent="70%"
複製代碼
ConstraintLayout layout_constraintHorizontal_chainStyle
Guideline
layout_constraintHorizontal_bias layout_constraintVertical_bias
px=dp*density
,動態修改設備的density值,在不一樣分辨率下達到相同的像素密度補間動畫: 主要經過xml中定義具備旋轉、縮放、平移、透明度的動畫
Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.viewanimation);
textView.startAnimation(animation);
複製代碼
屬性動畫: 補間動畫只能定義兩個關鍵幀在透明(alpha)、旋轉(rorate)、位移(translate)和縮放(scale)這四個屬性的變換,可是屬性動畫能夠定義任何屬性的變化。 補間動畫只能對 UI 組件執行動畫,但屬性動畫能夠對任何對象執行動畫。
Animator
: 提供建立屬性動畫的基類,基本不會直接使用這個類。 ValueAnimator
:屬性動畫用到的主要的時間引擎,負責計算各個幀的屬性值。 ObjectAnimator
: ValueAnimator 的子類,對指定對象的屬性執行動畫。 AnimatorSet
:Animator 的子類,用於組合多個 Animator。
定義:給HTTP增長一個安全層,用於保障HTTP的加密傳輸,能夠接受的對稱加密,非對稱加密,hash算法 Https在與服務器進行數據交互以前,會與服務器進行一次通訊(握手)
一、瀏覽器將自身支持的加密算法發送給服務端
二、服務端篩選出一套加密算法,以證書的形式發給瀏覽器
三、瀏覽器根驗證證書的合法性,據拿到的證書裏的公鑰加密一串消息發給服務端
四、服務端使用私鑰解密信息,驗證哈希,並加密響應消息給瀏覽器
五、瀏覽器解密響應消息,並對消息進行驗證,若是驗證經過,則能夠進行加密數據交互
解決觸摸事件衝突:
外部攔截。ViewGroup重寫onInterceptTouchEvent方法,默認不攔截,事件往下分發給子View,若返回true,則攔截這次事件,將事件傳給ViewGroup的onTouchEvent處理。
內部攔截。重寫子View的dispatchTouchEvent方法,方法中調用getParent().requestDisallowInterceptTouchEvent(true)方法,傳true則表明不但願ViewGroup攔截事件,傳false則表明但願ViewGroup攔截事件。
內部攔截。子View重寫onTouchEvent方法,返回true,則子View消費該次事件,返回false,該次事件返回給ViewGroup的onTouchEvent處理。