Nos vídeos e artigos anteriores, apresentamos os conhecimentos básicos necessários para todo o desenvolvimento de aplicativos Android para veículos:
- [Transcrição do vídeo] Desenvolvimento e análise de aplicativos Android montados em veículos - No sistema operacional montado em veículos - Nuggets
- [Transcrição do vídeo] Desenvolvimento e análise de aplicativos Android de veículos - download e compilação AOSP - Nuggets
- [Transcrição do vídeo] Desenvolvimento e análise de aplicativos automotivos Android - Desenvolvimento de aplicativos de sistema - Nuggets
- [Transcrição do vídeo] Desenvolvimento e análise de aplicativos Android montados em veículos - Prática e empacotamento de AIDL (Parte 1) - Nuggets
- [Transcrição do vídeo] Desenvolvimento e análise de aplicativos Android montados em veículos - Prática e empacotamento de AIDL (Parte 2) - Nuggets
Nesta edição, apresentamos a implementação de aplicativos veiculares no Android Automotive nativo e seus princípios. A primeira coisa que quero apresentar é um aplicativo de sistema muito importante no desenvolvimento de aplicativos veiculares, a UI do sistema Android - SystemUI
.
Como o sistema Android nativo SystemUI
possui uma grande quantidade de código e um conteúdo muito complexo, selecionarei aqui SystemUI
módulos que são de referência para o desenvolvimento de veículos e os apresentarei. Haverá cerca de 4 a 5 edições de conteúdo, que são divididas principalmente em os seguintes módulos:
- Desenvolvimento e análise de aplicativos Android para automóveis - Análise de "função" e "estrutura de código-fonte" do SystemUI - Nuggets
- Desenvolvimento e análise de aplicativos Android para carros - primeiro experimente o plug-in SystemUI
O código-fonte do SystemUI pode ser o mais complexo de todos os aplicativos nativos do Android. Quando precisamos customizar o SystemUI, a enorme quantidade de código-fonte trará enormes riscos potenciais para o desenvolvimento customizado. Portanto, a prática comum atual para SystemUI montado em veículos é transplantar uma pequena quantidade de código-fonte necessário do SystemUI nativo e, em seguida, personalizar um SystemUI com código-fonte e funções totalmente controláveis do zero.
O redesenvolvimento de um SystemUI é a única opção? claro que não! Os funcionários do Google já perceberam esse problema há muito tempo, então o SystemUI fornece um método de desenvolvimento de plug-in - SystemUI Plugin.
Endereço do código-fonte deste artigo: /frameworks/base/+/refs/heads/main/packages/SystemUI/plugin/ExamplePlugin/
O ambiente do código-fonte deste artigo é baseado no Android 13
Plug-ins SystemUI
O mecanismo de plug-in SystemUI é um método que permite que as funções do SystemUI sejam substituídas ou modificadas dinamicamente, permitindo que os desenvolvedores criem e iterem rapidamente protótipos do SystemUI enquanto modificam a estrutura principal do SystemUI o mínimo possível .
Obs: Usar Plugin não garante que não precisaremos modificar o framework principal do SystemUI, afinal as necessidades estão sempre mudando.
Ganchos de plug-in
Ganchos de plug-in são interfaces de plug-in predefinidas que permitem que aplicativos implementem funções específicas e registrem e declarem tipos e versões de plug-ins por meio de intenções e anotações. Existem muitos tipos de ganchos de plug-in, como OverlayPlugin, QSFactory, VolumeDialog, etc. Cada tipo possui uma ação correspondente e uma interface esperada, que são usadas para identificar as funções e requisitos do plug-in.
As interfaces predefinidas para ganchos de plug-in no Android 13 incluem principalmente o seguinte:
- BcSmartspaceDataPlugin : Este plugin permite que o aplicativo forneça dados personalizados ao espaço inteligente (BcSmartspace) na interface da tela de bloqueio, como clima, calendário, notícias, etc.
- ClockProviderPlugin : Este plugin permite que os aplicativos forneçam estilos de relógio personalizados para interfaces de tela de bloqueio e aplicativos sempre ativos.
- DozeServicePlugin : Este plugin permite que os aplicativos personalizem o comportamento do modo Doze, como controlar o brilho da tela, exibir conteúdo, sensores, etc.
- FalsingPlugin : Este plugin permite que as aplicações personalizem a detecção e o processamento de eventos de toque falso (Falsing), como determinar se o usuário realmente deseja deslizar a barra de notificação ou desbloquear a tela.
- GlobalActions : Este plugin permite que os aplicativos personalizem a aparência e o comportamento da caixa de diálogo Ações Globais, como adicionar novos botões de ação ou alterar o estilo da caixa de diálogo.
- GlobalActionsPanelPlugin : Este plugin permite que o aplicativo adicione um painel expansível à caixa de diálogo de operações globais para exibir mais opções ou informações de operação.
- IntentButtonProvider : Este plugin permite que o aplicativo adicione um botão personalizado na interface da tela de bloqueio para iniciar um Intent especificado.
- NavigationEdgeBackPlugin : Este plugin permite que os aplicativos personalizem o comportamento do gesto de retorno da borda da barra de navegação (NavigationEdgeBack), como alterar a área de disparo ou efeitos de animação.
- NotificationListenerController : Este plugin permite que a aplicação controle a conexão e desconexão do serviço de ouvinte de notificação (NotificationListener), bem como obtenha eventos e dados de notificação.
- NotificationMenuRowPlugin : Este plugin permite que os aplicativos personalizem a aparência e o comportamento da barra de menu de notificação (NotificationMenuRow), como adicionar novos itens de menu ou alterar o estilo do menu.
- NotificationPersonExtractorPlugin : Este plugin permite que os aplicativos personalizem a lógica de extração de informações pessoais (NotificationPersonExtractor) das notificações, como identificar contatos ou avatares incluídos nas notificações.
- OverlayPlugin : Este plugin permite que o aplicativo personalize a visualização (OverlayView) que cobre a barra de notificação para exibir algum conteúdo ou funções adicionais.
- PluginFragment : Este plugin permite que o aplicativo incorpore um Fragment no SystemUI para exibir algumas interfaces ou funções personalizadas.
- QSFactory : Este plugin permite que os aplicativos forneçam uma fábrica de configurações rápidas personalizada (QSFactory) para criar blocos ou painéis de configurações rápidas.
- SensorManagerPlugin : Este plugin permite que aplicativos usem o serviço SensorManager para registrar e cancelar o registro de ouvintes de sensores e obter eventos e dados de sensores.
- ToastPlugin : Este plugin permite que os aplicativos personalizem a aparência e o comportamento das mensagens do Toast (Toast), como alterar a posição ou duração do Toast.
- ViewProvider : Este plugin permite que o aplicativo forneça uma visualização personalizada (View) para substituir determinados componentes ou funções no SystemUI.
- VolumeDialog : Este plugin permite que os aplicativos personalizem a aparência e o comportamento da caixa de diálogo de ajuste de volume (VolumeDialog), como adicionar novas opções de controle de volume ou alterar o estilo da barra de volume.
Habilidade de plug-in
Para criar um projeto de plug-in AndroidStudio SystemUI, você pode consultar as seguintes etapas:
1) Compilar SystemUIPluginLib.jar
Antes de usar o Plugin, precisamos compilá-lo SystemUIPluginLib.jar
e executar as seguintes instruções no diretório raiz do código-fonte AOSP.
make SystemUIPluginLib
Então você pode obtê-lo no diretório abaixoSystemUIPluginLib.jar
out/target/product/emulator_x86/obj/JAVA_LIBRARIES/SystemUIPluginLib_intermediates/javalib.jar
Na documentação do AOSP, é recomendado usar o script frameworks/base/packages/SystemUI/plugin/update_plugin_lib.sh para compilar SystemUIPluginLib.jar, mas encontrei um problema de configuração do ambiente durante a compilação.
2) Configurar assinatura do sistema
Configure a assinatura do sistema em build.gradle.
android {
...
signingConfigs {
sign {
storeFile file('system.keystore')
storePassword '123456'
keyAlias 'cardemo'
keyPassword '123456'
}
}
buildTypes {
release {
minifyEnabled false
signingConfig signingConfigs.sign
}
debug {
minifyEnabled false
signingConfig signingConfigs.sign
}
}
}
Sobre como fazer uma assinatura de sistema, consulte: Desenvolvimento e análise de aplicativos Android de veículos - Desenvolvendo aplicativos de sistema - Nuggets
3) Crie um plug-in
Defina uma classe no projeto do plugin para implementar vários plug-ins já fornecidos no Plugin, e use a anotação Requires para declarar os campos de destino e versão.Esses campos são usados para identificar o tipo e a versão do plug-in.
@Requires(target = OverlayPlugin.class, version = OverlayPlugin.VERSION)
public class SampleOverlayPlugin implements OverlayPlugin {
private static final String TAG = "SampleOverlayPlugin";
private Context mPluginContext;
private View mStatusBarView;
private View mNavBarView;
@Override
public void onCreate(Context sysuiContext, Context pluginContext) {
Log.d(TAG, "onCreate");
mPluginContext = pluginContext;
}
@Override
public void onDestroy() {
if (mInputSetup) {
mStatusBarView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
onComputeInternalInsetsListener);
}
Log.d(TAG, "onDestroy");
if (mStatusBarView != null) {
mStatusBarView.post(() -> ((ViewGroup) mStatusBarView.getParent()).removeView(mStatusBarView));
}
if (mNavBarView != null) {
mNavBarView.post(() -> ((ViewGroup) mNavBarView.getParent()).removeView(mNavBarView));
}
}
@Override
public void setup(View notificationShadeWindowView, View navBar) {
Log.d(TAG, "Setup");
if (notificationShadeWindowView instanceof ViewGroup) {
mStatusBarView = LayoutInflater.from(mPluginContext)
.inflate(R.layout.colored_overlay, (ViewGroup) notificationShadeWindowView, false);
((ViewGroup) notificationShadeWindowView).removeAllViews();
((ViewGroup) notificationShadeWindowView).addView(mStatusBarView);
}
if (navBar instanceof ViewGroup) {
mNavBarView = LayoutInflater.from(mPluginContext)
.inflate(R.layout.colored_overlay, (ViewGroup) navBar, false);
((ViewGroup) navBar).removeAllViews();
((ViewGroup) navBar).addView(mNavBarView);
}
}
}
Nota: Existem diferenças consideráveis no código do SystemUI em diferentes versões do Android. Por exemplo: o statusBar retornado na configuração (View statusBar, View navBar) no Android13 é na verdade NotificationShadeWindowView.
4) Registrar plug-in
Registre um serviço no AndroidManifest do projeto do plug-in e use os atributos de ação e permissão para especificar a interface e as permissões do plug-in, para que o SystemUI possa encontrar o plug-in por meio do Intent.
<uses-permission android:name="com.android.systemui.permission.PLUGIN" />
<application>
<service
android:name=".SampleOverlayPlugin"
android:exported="false"
android:label="@string/plugin_label"
tools:ignore="Instantiatable">
<intent-filter>
<action android:name="com.android.systemui.action.PLUGIN_OVERLAY" />
</intent-filter>
</service>
</application>
O nome pode ser encontrado na interface do plugin que implementamos.
Para garantir a segurança do sistema, SystemUI construiu duas linhas de defesa para carregamento de plugins:
A primeira linha de defesa é a verificação Build.IS_DEBUGGABLE. SysUI verifica Build.IS_DEBUGGABLE antes de verificar ou carregar qualquer plug-in no dispositivo para garantir que a compilação seja depurável.
A segunda linha de defesa é a autoridade de assinatura. Todos os plugins devem ser assinados pelo sistema e ter com.android.systemui.permission.PLUGIN
permissões para carregar qualquer um de seus códigos, caso contrário, uma violação será registrada e o plugin será ignorado.
5) Execute o plug-in
Envie plugin.apk para o diretório /system/priv-app/ do emulador do Android 13 e reinicie. Você pode ver o seguinte efeito:
- Todas as subvisualizações da NavBar são removidas e uma visualização vermelha é adicionada;
- Todas as visualizações filhas de NotificationShadeWindowView são removidas e uma visualização vermelha é adicionada.
Resumir
Este artigo testou primeiro o mecanismo de plug-in SystemUI. Ao escrever este artigo, descobri que havia muito pouca informação relacionada ao plug-in e até mesmo as informações oficiais estavam desatualizadas. Assim como o título, este artigo apenas experimentou brevemente o Plugin. Como usar o Plugin para personalizar um SystemUI que atenda totalmente às nossas necessidades? Escreveremos isso mais tarde, pois precisamos primeiro analisar os princípios do Plugin SystemUI. Com tão poucas informações, é quase impossível escrever um Plugin que atenda às necessidades sem entender os princípios. No processo de análise dos princípios, iremos gradualmente completar e compreender alguns conceitos do Plugin.
O texto acima é todo o conteúdo deste artigo. Obrigado pela leitura. Espero que seja útil para você.
Referências