Prévia do material em texto
PROGRAMAÇÃO MOBILE Camila Andrade Santos JNI, framework e APIs Objetivos de aprendizagem Ao final deste texto, você deve apresentar os seguintes aprendizados: Reconhecer o papel de framework e APIs no desenvolvimento de aplicativos. Identificar o uso da JNI no acesso a código nativo. Ilustrar o consumo de framework, APIs e JNI em uma aplicação mobile. Introdução Com a evolução tecnológica, o mercado tem exigido cada vez mais o desenvolvimento em larga escala de aplicações que abarcassem os mais diversos dispositivos. Em vista disso, para que as empresas consigam entregar aplicativos conforme a alta demanda, elas têm buscado utilizar o auxílio de frameworks e APIs que permitem o “reúso de código”, resultando em rapidez de construção de aplicações para os mais diversos aplicativos. Neste capítulo, você verá a diferença entre frameworks e APIs, bem como suas exemplificações durante o desenvolvimento de aplicações mobile, além de observar o funcionamento do uso de JNI seguido de um exemplo prático. 1 Frameworks e APIs A demanda por desenvolvimento de software desktop, web ou mobile tem au- mentado devido à crescente aceitação e utilização de dispositivos tecnológicos pela população. Na década de 1970, ocorreu a denominada “crise do software”, termo que expressa as difi culdades de desenvolvimento de software diante do crescimento acelerado da demanda, da complexidade dos problemas a serem resolvidos e da inexistência de técnicas estabelecidas para o desenvolvimento de sistemas que funcionassem adequadamente ou pudessem ser validados. Nesta década houve muitos problemas relacionados a prazos e custos no desenvolvimento de software, o que ocorreu devido à baixa produtividade, baixa qualidade de desenvolvimento e difícil manutenção de software. Além desses problemas, havia imprecisão nas estimativas de prazos e custos, pro- blema de produtividade das pessoas da área de desenvolvimento de software, o que não acompanhava a demanda de desenvolvimento; prazos ultrapassados; custos acima dos previstos; além do que, a facilidade com a manutenção não era discutida durante o desenvolvimento do sistema, com isso os custos de manutenção acabavam sendo altos. Um exemplo da crise do desenvolvimento de software é a Ariane 5 — projeto espacial da agência Europeia que custou em torno de US$ 8 bilhões, durou 10 anos de desenvolvimento, e explodiu cerca de 40 segundos após sua decolagem, causando na destruição do foguete e da carga um prejuízo avaliado em mais de US$ 500 milhões (MATSUBARA, 1997). A falha foi causada devido à conversão de dados de ponto flutuante de 60 bits para o valor inteiro assinado de 16 bits. O valor convertido possuía um valor maior que o que poderia ser representado por um número inteiro assinado de 16 bits. Para contornar tal situação e tentar minimizar a distância entre o desenvol- vimento do hardware e do software criou-se uma área de estudo denominada engenharia de software, na qual se buscou elaborar melhores metodologias e ferramentas para o desenvolvimento de software. A engenharia de software auxiliou principalmente a linguagem de programação (procedimental, modular e orientada a objetos) e a sistematização e automatização da documentação do programa e testes (PRESSMAN; MAXIM, 2016). Após tantas melhorias atribuídas ao processo de desenvolvimento de soft- ware, atualmente temos disponíveis diversas linguagens de programação, ambientes de desenvolvimento (IDEs — integrated development environment), frameworks, APIs (application programming interface), bibliotecas, dentre outros, para otimizar e padronizar o processo de desenvolvimento. Nesta seção discutiremos acerca de frameworks e APIs. Uma API nada mais é do que uma maneira de integrar sistemas, de forma que os dados trocados entre os sistemas tenham segurança e que haja facilidade nesta troca de informações, mesmo que os sistemas tenham linguagens de programação distintas. Assim, podemos resumir que uma API é um conjunto de definições e protocolos usados no desenvolvimento e na integração de software (RED HAT, [2020?]). Quando falamos que uma API pode comunicar um sistema a outro, você pode se perguntar: “mas por que um software iria se comunicar com outro?”. Atualmente, há disponível na internet uma infinidade de serviços e produtos que podem compor um sistema de forma a agilizar seu processo de desen- volvimento. Por exemplo, caso você esteja desenvolvendo um sistema que irá JNI, framework e APIs2 monitorar ou apresentar a localização para o usuário, você não precisa imple- mentar um serviço de mapas do início, você pode simplesmente utilizar a API do Google Maps. A utilização de APIs acaba simplificando o desenvolvimento de aplicações, pois não é necessário saber como a API foi implementada, e gera-se, com isso, economia de recursos, como tempo, dinheiro e pessoal. As APIs costuma ser vistas como contratos, com documentações que representam um acordo entre as partes interessadas, ou seja, os software que se comunicarão. Se uma das partes enviar uma solicitação remota estruturada de uma forma específica, estará determinando como o software da outra parte responderá. Observe a Figura 1. Figura 1. Exemplo do funcionamento de API baseado na documentação de Widnet. Fonte: Adaptada de OpenClipart-Vectors/Pixabay.com; Api Cep ([2020?]); Samuel1983/Pixabay.com. No exemplo exposto na Figura 1, temos uma API que retorna para o usuário um endereço conforme um CEP requisitado. Na chamada da API, por meio da URL, conforme documentação, passa-se o CEP que se deseja encontrar o endereço, e ao final o formato que deseja receber o retorno. Em nosso exemplo, requisitamos um retorno no formato JSON, desta forma a resposta da API foi o endereço em JSON. Neste caso em nosso aplicativo, tratamos esse retorno para que possamos operar sobre esses dados. Com isso, temos um contrato sobre como a mensagem deve ser enviada, e qual será o retorno dela sempre que requisitarmos. E isso acontecerá para todo tipo de API. Desta forma, temos que a utilização de API simplifica a forma com que desenvolvedores integram novos componentes de aplicações a uma arquitetura já existente, pois com as tecnologias evoluindo bem como os desejos dos clientes, as necessidades empresariais podem mudar rapida- mente para responder a este mercado em constante transformação. Porém 3JNI, framework e APIs não podemos nos ater ao conceito de APIs como sendo somente a busca por algo externo ao sistema, pois há APIs que podem funcionar internamente, evitando o retrabalho. Framework, por sua vez, está relacionado a “como fazer”. De maneira geral, um framework é um modelo de códigos já existentes para uma função específica, sendo esta função necessária para o desenvolvimento de software. Portanto frameworks possuem códigos comuns a diversos projetos, para que não seja necessário que os desenvolvedores produzam um novo código para funções que já existam. O objetivo principal de frameworks é basicamente oferecer determinadas funcionalidades prontas, como por exemplo, inserção de um campo de texto ou campo de data, otimizando o tempo dos programadores com comandos básicos. Tais funcionalidades posteriormente podem ser utilizadas para o desen- volvimento de novos projetos, e com isso pode-se atingir mais produtividade e focar em questões mais importantes, como por exemplo, a regra de negócio do sistema e a lucratividade ao reduzir custos e tempo. Observe a Figura 2. Figura 2. Estrutura de uma casa. Fonte: Globalplac (2019, documento on-line). Imagine que a estrutura da casa exposta na Figura 2 seja um framework. O dono da casa define de que material serão as paredes, o telhado, como será a decoração, quais móveis conterão na casa, porém a estrutura da casa já está pronta. Se outra pessoa desejar fazer uma casa com este framework, a estrutura será a mesma, apenas os detalhes serão outros. Da mesma forma acontece no desenvolvimento. Caso as empresas “X” e “Y” desejem utilizarJNI, framework e APIs4 o mesmo framework, ambas trabalharão sobre a mesma estrutura, todavia o resultado poderá ser totalmente diferente. Há ainda um terceiro conceito, em que comumente há confusões: biblio- tecas. Quando buscamos por “biblioteca em programação”, encontramos diversos resultados relacionados a “reúso de código”, “soluções de problemas comuns da computação por meio de funções ou métodos”, “poupar tempo”, entre outros. Tais resultados são semelhantes ao que o framework provê, e com isso tem-se a confusão. Bibliotecas são uma coleção de implementações de comportamentos escritos em uma linguagem que é importada para seu código, como por exemplo, a utilização da biblioteca java.lang.Math, da linguagem Java, que contém pequenos métodos para executar operações numéricas básicas. Dependendo da aplicação não é necessário importá-la por completo, basta importar apenas o que irá utilizar, como por exemplo, java.lang.Math.sqrt para cálculo de raiz quadrada. Já um framework é uma estrutura real ou conceitual, que busca servir como um guia para a construção de algo no qual o que será construído herdará as características desta estrutura. Neste caso você não pode escolher o que importar, já que o framework decide o “como” será feito. 2 JNI — Java Native Interface Uma das formas de desenvolver aplicações Android é utilizando o Native Development Kit (NDK), que é um conjunto de ferramentas que permitem incorporar códigos em linguagem C ou C++ em aplicações Android, permitindo a utilização de códigos nativos. A utilização de códigos nativos em aplicações Android pode ser desejada quando desenvolvedores buscam portabilidade das aplicações entre plataformas, reutilizar bibliotecas existentes ou fornecer suas próprias para reutilização, ou ainda, melhorar o desempenho em determinados casos, em especial nos de computação intensa, como jogos. Para que uma aplicação seja considerada “nativa”, ela deve possuir os componentes a seguir (ANDROID DEVELOPERS, [2020?]). Bibliotecas compartilhadas nativas: o NDK compila as bibliotecas ou arquivos com extensão .so a partir de código fonte C/C++. Bibliotecas estáticas nativas: o NDK pode compilar bibliotecas estáti- cas ou arquivos com extensão .a que podem ser vinculados a outras bibliotecas. 5JNI, framework e APIs Java Navite Interface (JNI): é uma interface de comunicação entre os componentes Java e C++. Interface Binárias de APP (ABI): define como deverá ser a interação entre o código de máquina do app e o sistema no momento da execução. Nesta seção focaremos no componente JNI. Para compreendermos a dife- rença entre a compilação de uma aplicação nativa Android e uma aplicação Android Java, temos que o Java é executado na máquina virtual Dalvik Virtual Machine, enquanto o código nativo é compilado em códigos binários em execução diretamente no sistema operacional (LIU, 2013). Assim, é necessário obter uma interface entre os “dois mundos”, para isso existe a JNI. Observe na Figura 3 o relacionamento entre o código Java e o código nativo. Figura 3. Relacionamento entre o código Java e código nativo. Fonte: Liu (2013, p. 39). Neste relacionamento podemos observar o código Java executando sob a máquina virtual, enquanto que o código nativo comunica-se diretamente com o sistema operacional. Para que o código Java se comunique com o código nativo, é necessário antes passar pelo JNI, a ponte entre o que está executando na máquina virtual e o código nativo, permitindo que o código Java invoque métodos nativos. Desta forma a JNI facilita a comunicação bidirecional entre os dois tipos de códigos. Como vimos, o JNI fornece um conjunto de funções C/C++ capazes de interagir com objetos Java. Tais funções são compostas por funções genéricas e outras específicas do programa para possibilitar a interação com o código escrito em Java. Os componentes nativos são compiladores, de modo que JNI, framework e APIs6 se crie uma biblioteca dinâmica, como por exemplo, .DDL ou ponto .so, que será importada pela classe Java que estabelece a interface com o código nativo, com isso o código escrito em Java poderá interagir com o código escrito em C/C++. Na visão do Java, os objetos são passados como parâmetros para a função nativa, que por sua vez pode alterar dados desses objetos, executar seus métodos e retornar valores que também podem ser objetos Java. Assim, é transparente para o programa que a função chamada é nativa, e não Java. Na visão do C/C++, deve-se implementar as funções a serem utilizadas em Java seguindo a convenção especificada por JNI para a escolha dos protótipos das funções/métodos. Os componentes C ou C++, quando em execução, podem utilizar quaisquer recursos, como se fossem um programa à parte regido em mesma linguagem. Ou seja, significa que se aplicam todas as preocupações quanto ao uso de memória alocada dinamicamente, vazamento de memória, uso correto de ponteiros, perda de referência a recursos tais como arquivos abertos, dentre outros (LIANG, 1999). Outra questão a ser observada está relacionada com a portabilidade dessas funções. Além de uma biblioteca dinâmica criada em uma plataforma não servir em outra, muitas funções C ou C++ são dependentes do compilador, do ambiente de desenvolvimento e possivelmente até do sistema operacional utili- zado ao compilador. Por isso, deve-se evitar o uso de recursos potencialmente incompatíveis entre plataformas de desenvolvimento e de execução, como por exemplo, o uso de bibliotecas vinculadas a uma determinada plataforma. Caso não sejam tomados alguns cuidados ao desenvolver aplicativos utilizando JNI, pode-se ter mais desvantagens do que vantagens. Existem frameworks para diversos fins, como auxiliar a acessar bancos de dados ou facilitar a manipulação de imagens. Veja alguns exemplos de frameworks Android: Ormlite: facilita trabalhar com o banco de dados local SQLite, poupando o desen- volvedor de escrever na linguagem SQL. Retrofit: facilita a integração de serviços REST de forma segura. Android Universal Image Loader: acelera o carregamento das imagens utilizando cache em memória e em disco. Robolectric: facilita no desenvolvimento e execução de testes. Appcelerator Titanium: oferece uma interface para projetar e desenvolver aplicativos visualmente, por meio de “arrasta e solta”. 7JNI, framework e APIs 3 Frameworks, APIs e JNI em aplicações Android A seguir, abordaremos a utilização de cada uma dessas ferramentas aplicadas à construção de aplicações Android. Framework — IONIC Para exemplifi car a utilização de frameworks, vamos utilizar o framework IONIC. IONIC é um framework grátis e open source otimizado para criar aplicativos híbridos com html5, CSS e JavaScript para IOS6+ e Android 4.0+. Com a utilização deste framework, podemos reduzir pela metade o custo de desenvolvimento de aplicações, uma vez que pode-se produzir, em uma única vez, uma aplicação para Android e IOS, em vez de focar mão de obra para o desenvolvimento de aplicações em separado. Para utilizar o IONIC, é necessário efetuar sua instalação, primeiramente, utilizando o comando npm install -g @ionic/cli. Após instalado, vamos criar um projeto. Ao criar um projeto, podemos escolher entre três tem- plates, sendo um vazio (blank). Essa página contém uma página simples com código JavaScript mínimo; um com menu (sidemenu), este modelo possui várias páginas com todos os menus laterias; e um sem menu lateral (PHAN, 2015). Após ter selecionado um modelo, vamos criar nosso projeto por meio do co- mando ionic start <nome do aplicativo> <modelo>. Nesta unidade utilizaremos o modelo sidemenu e o nome do projeto será MeuApp (Figura 4). $ ionic start MeuApp sidemenu Figura 4. Iniciando um aplicativo mobile com Ionic. JNI, framework e APIs8 Aparecerá uma opção para utilizar o framework Angular ou React. Neste exemplo iremos utilizar a opção Angular. Após o término da construção do projeto, aparecerá uma mensagem comoda Figura 5. Figura 5. Término da construção da aplicação mobile com Ionic. Para verificarmos como está nosso aplicativo, basta digitar o comando “entrar” na pasta do aplicativo que criamos utilizando o comando cd MeuApp, e, em seguida, executar o comando ionic serve. Este comando indica que a aplicação será executa no navegador. Caso desejemos executar em um emulador Android, executaremos o comando ionic emulate android, ou ainda, para executar em um dispositivo, executamos o comando ionic run android, como exposto na Figura 6. Figura 6. Execução da aplicação mobile no navegador. 9JNI, framework e APIs Quando a aplicação concluir o processo de inicialização, apresentará a URL para acesso — no nosso caso é http://localhost:8100. No navegador teremos a saída apresentada na Figura 7. Figura 7. Resultado da aplicação mobile utilizando o framework Ionic. Dessa forma podemos criar nossa aplicação com base neste modelo. Para compilar o aplicativo para Android executamos o comando ionic build android, e para IOS, ionic build ios. Podemos notar a facilidade no desenvolvimento de aplicações utilizando frameworks. JNI, framework e APIs10 API — Google Maps Como um exemplo de utilização de API em aplicações Android temos a utilização de mapas. Ao invés de implementarmos um novo mapa, podemos consumir uma API de mapa fornecida pelo Google. Por meio do link https:// console.developers.google.com/cloud-resource-manager criaremos um projeto que receberá a API do Google. No link https://console.developers.google.com/ apis/library podemos verifi car todas as APIs disponibilizadas pelo Google. Vamos utilizar a API “Maps SDK for Android”. Ao encontrar clique em “ativar”. Após a API estar ativa na sua conta, é necessário gerar uma credencial para que sua aplicação possa acessar a API. Observe a Figura 8. Figura 8. Geração de credencial para acessar a API Google Maps. Para geração da credencial, vamos no menu, aba “APIs e serviços” e, em seguida, “credenciais”, “criar credenciais” e “chave de API”. Será gerada uma credencial para que possamos utilizar em nosso aplicativo para comunicar e consumir a API do Google Maps. De forma geral, a comunicação entre APIs e aplicações são autenticadas por meio de tokens ou chaves. 11JNI, framework e APIs Figura 9. Geração de credencial para acessar a API Google Maps. Lembre-se de marcar a opção “Apps para Android”. O funcionamento é similar caso queira que a aplicação se comunique com aplicações IOS. A chave gerada está apresentada no campo “API Key”. Esta API Key será inserida no arquivo strings.xml como apresentado na linha 3 da Figura 10. Figura 10. Inserção da API Key do Google Maps no projeto. No arquivo AndroidMainfest.xml adicione o código exposto a seguir, da configuração do arquivo AndroidMainfest.xml, que permitirá o acesso à rede externa. <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission. ACCESS _ FINE _ LOCATION"/> JNI, framework e APIs12 <uses-permission android:name="android.permission.WRITE _ EXTERNAL _ STORAGE" android:maxSdkVersion="22" /> <uses-permission android:name="android.permission.READ _ EXTERNAL _ STORAGE" android:maxSdkVersion="22" /> No arquivo activity_main.xml, insira o fragmento do código a seguir, que fará com que apareça o Google Maps na tela. <?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/ android" android:id="@+id/map" android:layout _ width="match _ parent" android:layout _ height="match _ parent" class="com.google.android.gms.maps.SupportMapFrag- ment" /> Na classe Java que irá carregar o mapa, vamos inserir o código a seguir. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity _ main); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager(). findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap map) {2 map.addMarker(new MarkerOptions().position(new La- tLng(-25.443150, -49.238243)).title("Jardim Botânico")); } 13JNI, framework e APIs O resultado é exposto na Figura 11. Figura 11. API Google Maps. JNI, framework e APIs14 JNI — Olá mundo! Para exemplifi car o funcionamento de JNI em aplicações, vamos construir um exemplo simples, criando uma biblioteca que imprima “Olá Mundo” no terminal. Para este exemplo foi utilizado o sistema operacional Ubuntu 18.04.4 LTS e o JDK 1.8.0. Criaremos uma pasta para guardar nossos arquivos e, dentro dela, um arquivo com a extensão .java. Neste arquivo inseriremos o código exposto na Figura 12. Figura 12. Código do arquivo HelloWorld.java. Fonte: Liu (2013, p. 39). Após a declaração da classe HelloWorld na primeira linha, declaramos o método nativo print(). No método principal, nomeado de main, chamamos o método print() da nossa classe atual. Na linha 7, carregamos a biblioteca com a extensão .so, chamamos o método loadLibrary e passamos por parâmetro o nome da biblioteca que criamos. Observe que há uma diferença entre a declaração de métodos nativos e de métodos Java. Quando deseja-se utilizar métodos nativos, a declaração deve conter o modificador native. Após criarmos a classe .java, vamos compilá-la via terminal, utilizando o comando javac HelloWorld.java. Observe que na pasta do arquivo .java foi criado um arquivo de mesmo nome porém com a extensão .class. Em seguida, vamos criar um arquivo de cabeçalho que conterá a extensão .h. Este arquivo será criado por meio do comando javah –jni HelloWorld. O comando javah, cria um arquivo .h em linguagem C a partir de uma classe java, permitindo que ambas as linguagens se comuniquem. 15JNI, framework e APIs Em seguida, criaremos um arquivo com extensão .c com o nome Hello- World. Este arquivo conterá o conteúdo descrito na Figura 13. Figura 13. Código do arquivo HelloWorld.c. Fonte: Liu (2013, p. 39). Este código simplesmente imprime na tela o texto “Olá Mundo”. Após escrever o código em C, basta compilar para construir uma biblioteca nativa executável no Java. Para isso, execute o comando: gcc -shared -fpic -o libHelloWorld.so -I/usr/lib/jvm/jdk1.8.0 _ 241/ include -I/usr/lib/jvm/jdk1.8.0 _ 241/include/linux HelloWorld.c Este comando gerará em nossa pasta um arquivo .so no mesmo diretório de nossa pasta. O comando GCC (GNU Compiler Collection) é um compilador para linguagem de programação C/C++ . As flags –shared –fpic são utilizadas para evitar a realocação de texto em arquiteturas que suportam bibliotecas compartilhadas dependentes da posição. A flag –o é utilizada para escrever a saída de um código compilado para um arquivo executável. No nosso exemplo, utilizamos o arquivo com a extensão .so. A flag –I é utilizada para encontrar as bibliotecas criadas (LIANG, 1999). Arquivos com extensão .so são bibliotecas que contém bibliotecas com- partilhadas carregadas dinamicamente para aplicativos Unix/Linux (LIANG, 1999). Para executarmos nosso aplicativo em um computador Linux para teste, é necessário copiar o arquivo libHelloWorld.so para o diretório /usr/lib/ jvm/jdk1.8.0_241/jre/lib/amd64/. Após adicionar a biblioteca na pasta do JRE, podemos executar nosso arquivo HelloWord.java implementado na Figura 14. A execução será feita por meio do comando java HelloWord. JNI, framework e APIs16 Figura 14. Execução do arquivo HelloWorld.java. Fonte: Liu (2013, p. 39). Observe que, ao executarmos o arquivo, será impresso no terminal o texto que inserimos no arquivo .c implementado na Figura 13. Para utilizar JNI em aplicações Android, no SDK versão 3.6.1, vamos criar um projeto Native C++, como exposto na Figura 15. Figura 15. Criação de projeto Native para Android. Observe que serão gerados um arquivo .cpp e um .txt. A classe .cpp conterá as funções desenvolvidas em linguagemnativa, como exposta no arquivo .cpp do código a seguir. 17JNI, framework e APIs #include <jni.h> //Função de adição extern "C" JNIEXPORT jint JNICALL Java _ com _ example _ jniexemplo _ MainActivity _ add( JNIEnv *env, jobject, jint x, jint y) { return x + y; } //Função de subtração extern "C" JNIEXPORT jint JNICALL Java _ com _ example _ jniexemplo _ MainActivity _ sub( JNIEnv *env, jobject, jint x, jint y) { return x - y; } //Função de multiplicação extern "C" JNIEXPORT jint JNICALL Java _ com _ example _ jniexemplo _ MainActivity _ multiply( JNIEnv *env, jobject, jint x, jint y) { return x * y; } //Função de divisão extern "C" JNIEXPORT jint JNICALL Java _ com _ example _ jniexemplo _ MainActivity _ divide( JNIEnv *env, jobject, jint x, jint y) { return x / y; } Em nossa aplicação, trata-se de funções matemáticas que retornam ope- rações entre números inteiros. Observe o tipo de dado jint. No arquivo .txt faremos a configuração de nossa aplicação nativa. Em add_library adicionaremos o diretório do nosso arquivo .cpp criado no último código que vimos. Observe esta configuração a seguir. # For more information about using CMake with Android Studio, # read the documentation: https://d.android.com/studio/projects/ add-native-code.html JNI, framework e APIs18 # Sets the minimum version of CMake required to build the # native library. cmake _ minimum _ required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add _ library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). native-lib.cpp ) # Searches for a specified prebuilt library and stores the path # as a variable. Because CMake includes system libraries in # the search path by default, you only need to specify the name # of the public NDK library you want to add. CMake verifies that # the library exists before completing its build. find _ library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target li # brary. You can link multiple libraries, such as libraries you # define in this build , prebuilt third-party libraries, or # system libraries. target _ link _ libraries( # Specifies the target library. 19JNI, framework e APIs native-lib # Links the target library to the log library # included in the NDK. ${log-lib} ) Em seguida, já podemos chamar nossa função nativa no arquivo .java. Observe o código a seguir. package com.example.jniexemplo; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity _ main); TextView exemplo = findViewById(R.id.exemplo); int a = add(1, 1); exemplo.setText("A soma é: " + Integer.toString(a)); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. JNI, framework e APIs20 */ public native int add (int x, int y); public native int sub (int x, int y); public native int multiply (int x, int y); public native int divide (int x, int y); } Assim como no exemplo Java para desktop que fizemos, devemos carregar a biblioteca. Nas linhas 11 a 13 é feita a importação desta biblioteca. Nas linhas 31 a 34 estamos “traduzindo” as funções escritas em nosso arquivo .cpp para o Java. Observe esta indicação pelo modificador native. Em nosso método onCreate, fazemos a operação de soma passando como parâmetro 1 e 1, e na linha 23 mandamos imprimir na tela o resultado da soma. O resultado desta aplicação simples é apresentado na Figura 16. Figura 16. Resultado. Desenvolver aplicações Android oferece vários desafios, mas utilizar as ferramentas corretas pode auxiliar neste processo e tornar o desenvolvimento mais rápido e eficiente. Frameworks de desenvolvimento oferecem solu- ções pré-moldadas nas quais o desenvolvedor pode se apoiar para otimizar a construção do seu aplicativo. Bibliotecas e APIs oferecem serviços prontos e testados que o desenvolvedor pode recorrer para melhorar o desempenho de 21JNI, framework e APIs sua aplicação. Este é o caso de aplicações nativas que recorrem ao JNI para executar partes mais custosas do código. Mesmo que um desenvolvedor não utilize todas as ferramentas existentes, é importante conhecer o leque de opções para tomar decisões coerentes e seguras no desenvolvimento de seu aplicativo. ANDROID DEVELOPERS. NDK: conceitos. Android Developers, [s. l.], [2019?]. Disponível em: https://developer.android.com/ndk/guides/concepts?hl=pt-br. Acesso em: 22 maio 2020. API CEP. API de consulta. API Cep, [s. l.], [2020?]. Disponível em: https://apicep.com/api- -de-consulta/. Acesso em: 22 maio 2020. GLOBALPLAC. Esquema estrutural Wood Frame. 2019. 1 desenho técnico. Disponível em: https://www.nucleodoconhecimento.com.br/engenharia-civil/steel-frame. Acesso em: 22 maio 2020. LIANG, S. The Java native interface: programmer's guide and specification. Boston: Addison-Wesley Professional, 1999. LIU, F. Android native development kit cookbook. Birmingham: Packt, 2013. MATSUBARA, T. Ariane 5: Who dunnit? IEEE Software, [s. l.], n. 0740-7459, p. 15-16, 1997. Disponível em: http://www.inf.ed.ac.uk/teaching/courses/seoc/2008_2009/resources/ ariane5.pdf. Acesso em: 22 maio 2020. PHAN, H. Ionic Cookbook. Birmingham: Packt, 2015. PRESSMAN, R. S.; MAXIM, B. R. Engenharia de software: uma abordagem profissional. 8. Porto Alegre: AMGH, 2016. RED HAT. O que significa API e como ela funciona. Red Hat, [s. l.], [2020?]. Disponível em: https://www.redhat.com/pt-br/topics/api/what-are-application-programming- -interfaces. Acesso em: 22 maio 2020. Os links para sites da web fornecidos neste livro foram todos testados, e seu funciona- mento foi comprovado no momento da publicação do material. No entanto, a rede é extremamente dinâmica; suas páginas estão constantemente mudando de local e conteúdo. Assim, os editores declaram não ter qualquer responsabilidade sobre qualidade, precisão ou integralidade das informações referidas em tais links. JNI, framework e APIs22