AndroidManifest 是什么,對(duì)不起,我不需要 ^-^

前言

在寫 Android 應(yīng)用時(shí),當(dāng)你新建一個(gè) Activity,ServiceContentProvider,Broadcast(著名的四大組件)時(shí),你是不是經(jīng)常性的寫完就直接運(yùn)行,然后程序就崩潰了,通過查看日志,你才發(fā)覺原來忘記在 AndroidManifest.xml 中進(jìn)行注冊(cè)。甚至于,當(dāng)我們代碼運(yùn)行需要某些權(quán)限時(shí),你也要跳轉(zhuǎn)到 AndroidManifest.xml 中進(jìn)行權(quán)限聲明,然后代碼才能正確運(yùn)行,而這些操作,我們往往都會(huì)忘記。

筆者個(gè)人認(rèn)為,導(dǎo)致我們經(jīng)常性忘記在 AndroidManifest.xml 中進(jìn)行注冊(cè)的一個(gè)主要的原因就在于編寫代碼和進(jìn)行注冊(cè)是發(fā)生在兩個(gè)文件中的,也就是我們需要進(jìn)行文件切換,這種切換操作對(duì)于我們正在編寫程序的思路起到了切斷作用,所以我們往往在專注于寫代碼的時(shí)候,就會(huì)忘記進(jìn)行組件注冊(cè)。

基于以上原因,筆者開發(fā)了一套開源框架:InjectManifest,這套框架致力于解決上面我們提到的編寫代碼和進(jìn)行組件注冊(cè)需要進(jìn)行文件切換的不便,框架提供注解進(jìn)行注冊(cè),讓我們?cè)诰帉懴嚓P(guān)需要進(jìn)行注冊(cè)的代碼的同時(shí),可以很方便地直接使用注解進(jìn)行相關(guān)內(nèi)容的注冊(cè),再也無需切換到 AndroidManifest.xml 去做這些事。

優(yōu)點(diǎn)

  • 采用編譯期注解與自定義 Gradle 插件完成注冊(cè)過程,對(duì)程序運(yùn)行無任何影響;
  • 支持注解和原生 AndroidManifest.xml 協(xié)同工作,最終會(huì)將兩者結(jié)合起來,保留不一致的元素,相同的元素只保留一份;
  • 對(duì)支持的標(biāo)簽的所有屬性配置均支持;

缺點(diǎn)

  • 在每次使用注解注冊(cè)后,需要 rebuild 一下才能生成新的 AndroidManifest.xml文件,如果采用注解注冊(cè)后,直接運(yùn)行程序,可以看到新的 AndroidManifest.xml 也生成了,但是程序此時(shí)使用的是舊的(也就是原生的)AndroidManifest.xml配置。這個(gè)地方的原因我猜測應(yīng)該是 processDebugManifest/processReleaseManifest 運(yùn)行在 新的 AndroidManifest.xml 生成前,所以這個(gè)問題我猜測是不是可以有什么辦法把processDebugManifest/processReleaseManifest 放到文件生成后再執(zhí)行····這個(gè)地方我暫時(shí)也沒找出什么辦法進(jìn)行解決,如果有誰知道怎么解決這個(gè)問題的,麻煩跟我講下,謝謝。
  • 目前只支持 manifest,application,activity,service,receiver,provider,uses-permission 標(biāo)簽的解析,對(duì)于其他標(biāo)簽,無法進(jìn)行融合,在新生成的 AndroidManifest.xml 中這些元素不會(huì)被保留;

示例

  1. manifest 標(biāo)簽注冊(cè)
@InjectManifest(
        pkName = "com.yn.injectmanifest",
        installLocation = INTERNAL_ONLY,
        sharedUserId = "android.uid.system"
)

public class App extends Application {
}

rebuild 一下,你就可以看到 AndroidManifest.xml 變成這樣:

@InjectManifest

manifest 標(biāo)簽的其他屬性 @InjectManifest 均支持。

  1. application 標(biāo)簽注冊(cè)
@InjectApp(
        name = ".App", //you can full class name or just simply using a .classSimpleName
        label = "i am app",
        debuggable = TRUE,
        metaData = @InjectMetaData(name = "app/meta-data")
)
public class App extends Application {
}

rebuild 一下,你就可以看到 AndroidManifest.xml 變成這樣:

@InjectApp

application 標(biāo)簽的其他屬性 @InjectApp 均支持。

  1. activity 標(biāo)簽注冊(cè)
@InjectActivity(
        name = ".MainActivity",
        intentFilter = @InjectIntentFilter(
                action = {"android.intent.action.MAIN", "android.intent.action_whyn_test"},
                category = {"android.intent.category.LAUNCHER", "android.intent.category.whyn"},
                data = @InjectData(mimeType = "image/*")
        ))
public class MainActivity extends AppCompatActivity {}

rebuild 一下,你就可以看到 AndroidManifest.xml 變成這樣:

@InjectActivity

activity 標(biāo)簽的其他屬性 @InjectActivity 均支持。

  1. service 標(biāo)簽注冊(cè)
@InjectService(
        enabled = TRUE,
        name = ".FirstService",
        label = "Inject Service test",
        intentFilter = @InjectIntentFilter(
                action = "com.yn.action.FirstService",
                category = "com.yn.category.serviceTest",
                data = @InjectData(
                        host = "sdcard",
                        mimeType = "video/mp4",
                        path = "/sdcard/1.MP4",
                        pathPattern = ".*\\.mp4",
                        pathPrefix = "/sdcard/",
                        port = "-2",
                        scheme = "file"
                )
        ),
        metaData = @InjectMetaData(name = "com.yn.meta-data.service")
)
public class FirstService extends Service {···}

rebuild 一下,你就可以看到 AndroidManifest.xml 變成這樣:

@InjectService

service 標(biāo)簽的其他屬性 @InjectService 均支持。

  1. receiver 標(biāo)簽注冊(cè)
@InjectReceiver(
        name = ".FirstReceiver",
        label = "hi i am first receiver",
        process = ".remote",
        enabled = TRUE
)
public class FirstReceiver extends BroadcastReceiver {···}

rebuild 一下,你就可以看到 AndroidManifest.xml 變成這樣:

@InjectReceiver

receiver 標(biāo)簽的其他屬性 @InjectReceiver 均支持。

  1. provider 標(biāo)簽注冊(cè)
@InjectProvider(
        authorities = "com.yn.authorities",
        name = ".FirstProvider",
        label = "I am ContentProvider"
)
public class FirstProvider extends android.content.ContentProvider {···}
@InjectProvider

provider 標(biāo)簽的其他屬性 @InjectProvider 均支持。

  1. uses-permission 標(biāo)簽注冊(cè)
    @InjectUsesPermission({
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.BLUETOOTH,
            Manifest.permission.ACCESS_WIFI_STATE,
    })
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

rebuild 一下,你就可以看到 AndroidManifest.xml 變成這樣:

@InjectUsesPermission

uses-permission 標(biāo)簽的其他屬性 @InjectUsesPermission 均支持。

目前暫時(shí)就只支持以上所講的標(biāo)簽,后續(xù)我有時(shí)間就會(huì)不定時(shí)更新下。

下載

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.whyn:injectmanifest-plugin:1.1.0'
    }
}

然后,apply 到你的 module

apply plugin: 'com.android.application'
apply plugin: 'com.whyn.plugin.injectmanifest'

注意事項(xiàng):

  • InjectManifest 默認(rèn)會(huì)將生成的 AndroidManifest.xml 替換掉原來的 AndroidManifest.xml,但在替換前,會(huì)將原來的 AndroidManifest.xml 保存為 AndroidManifest_old.xml,所以,對(duì)于暫時(shí)未支持的 xml 標(biāo)簽,新生成的文件無法保留,那么你就可以從 AndroidManifest_old.xml 中找回。
    如果想更換上面的默認(rèn)行為,那就需要在 modulebuild.gradle 中增加下面的擴(kuò)展屬性:
manifestConfig {
    //the defautl AndroidManifest.xml path
    originManifestPath android.sourceSets.main.manifest.srcFile.absolutePath

    //the AndroidManifest.xml path generated by annotation processor
    genManifestPath "$project.buildDir/generated/source/apt/debug/Collections.xml"
    
    //to save the original AndroidManifest: true -- save,false -- not save
    saveOrigin false
}
  • 如果你在開發(fā)過程中,要為注解處理器傳遞參數(shù),請(qǐng)記住加上 + 號(hào),代表追加,否則,會(huì)導(dǎo)致 gradle 插件里面默認(rèn)設(shè)置的注解參數(shù)失效,這樣就不會(huì)合并原生 AndroidManifest.xml 了。
android {
    defaultConfig{
    ···
    ···
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += [xxxxx: 'yyyyy'] 
            }
        }
    }
}
  • 如果你對(duì) AndroidManifest.xml 的默認(rèn)路徑進(jìn)行了修改,如果你還希望能合并 AndroidManifest.xml,那你需要手動(dòng)傳遞最新路徑給 annotation processor
android {
    defaultConfig{
    ···
    ···
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AndroidManifestPath: android.sourceSets.main.manifest.srcFile.absolutePath] 
            }
        }
    }
}

附錄

源碼傳送門:InjectManifest
AndroidManifest.xml 應(yīng)用清單官方文檔: here

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評(píng)論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評(píng)論 25 709
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,253評(píng)論 6 342
  • 如有雷同,不是巧合。 大環(huán)境仍然是穩(wěn)定,國家政策是穩(wěn)健的貨幣政策和積極的財(cái)政政策,說白了就是不放水,搞...
    十二月的陽光閱讀 209評(píng)論 0 0
  • 已經(jīng)過去十天了,距離蘇荷在網(wǎng)上發(fā)布籌款開始。這期間,她每天都抱著那部有些破舊的手機(jī)查看銀行卡余額,然后將籌款一筆一...
    茶丁故事閱讀 1,005評(píng)論 6 23

友情鏈接更多精彩內(nèi)容