Tutorial Android – Entendendo e obtendo os dados do acelerômetro no Android

On 18 de janeiro de 2016 by Carlos Mion

Neste post iremos mostrar como manipular os dados do acelerômetro — obtenção, tratamento e salvamento em arquivo — no Android. O desenvolvimento usará o Android Studio e a versão 4.3 do Android.

Configuração do Ambiente para usar o Acelerômetro

     Após baixar o Android Studio e configurado o ambiente, comece um novo projeto. Este tutorial está se baseando na versão 4.3(JellyBean) do Android.

Criação do projeto:

Imagem 1.1
Imagem 1.1 : Tela inicial

    Note que foram criados dois arquivos xml, o activity_main.xml e o content_main.xml. O activity_main.xml é onde será feita a programação de layout(o que vai aparecer na tela) do nosso aplicativo. O content_main.xml pode ser deletado, pois é uma função extra nova no AndroidStudio que não será necessário ao nosso aplicativo e apenas o deixará mais pesado caso seja mantido. Então clique com o botão direito em cima do content_main.xml e vá em deletar, deixe o pop-up que aparece da seguinte forma:

Imagem 1.2
Imagem 1.2 : Pop-up de confirmação

    Ao clicar em “OK” a Imagem seguinte vai alertar que esse .xml está sendo usado pelo projeto, clique em Delete Anyway:

Imagem 1.3
Imagem 1.3 : Pop-up de confirmação 

    Após esse processo, o projeto se parecerá assim:

Imagem 1.4
Imagem 1.4 : MainActivity.java

    No Menu do lado esquerdo do monitor, vá em App > Res > layou> activity_main.xml

Imagem 1.5
Imagem 1.5 : activity_main.xml

    Na parte inferior da tela, clique em Text, para eliminar o vestígio que o arquivo content_main.xml deixou :

Imagem 1.6
Imagem 1.6 : activity_main.xml

    Remova a linha 

<include layout="@layout/content_main" />

e a linha

android:src="@android:drawable/ic_dialog_email"

    A tela do projeto deve estar assim:

Imagem 1.7
Imagem 1.7 : activity_main.xml

    Por último, vá em MainActivity.java e remova as linhas do método onCreate.

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
    }
});

e

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar);

    Isso foi para remover linhas desnecessárias ao código, as quais representavam o botão flutuante rosa que vimos na imagem 1.1 na parte de programação java do aplicativo.

 

 Registrando o Sensor

    Essa parte do Tutorial Serve não apenas para o acelerômetro, mas para qualquer sensor que você deseje adicionar em um aplicativo no futuro.

    Em MainActivity.java, na linha de declaração da classe, onde está escrito

public class MainActivity extends AppCompatActivity”

deixe

public class MainActivity extends AppCompatActivity implements SensorEventListener

Feito isso, o AndroidStudio vai acusar erro, para solucioná-lo basta selecionar a linha vermelha e apertar Alt+Enter, ele vai dar a sugestão de implementar os métodos necessários para o listener SensorEventListener seja implementado corretamente no projeto. Ao clicar em ImplementMethods, a seguinte tela aparecerá :

Imagem 2.1
Imagem 2.1 : Pop-up de confirmação de inserção de dados

    Clicando em OK, dois novos métodos serão adicionados ao seu MainActivity.java, OnSensorChanged e OnAccuracyChanged, que são os métodos que vem da classe SensorEventListener. O método OnSensorChanged é onde será programada toda a “reação” do aplicativo ao acelerômetro — uma vez que o mesmo é invocado pela plataforma Android todas as vezes que o acelerômetro sofre alguma modificação. Já o método onAccuracyChanged, apesar de necessário para que a aplicação compile, não sera necessário para o desenvolvimento desse tutorial e será deixado de lado.

    Agora vamos de fato registrar o SensorManager, o sensor acelerômetro e o seu Listener.

    Na linha seguinte à declaração da classe, declare

Sensor accelerometer;
SensorManager sensorManager;

    Aqui foram chamados de accelerometer e sensorManager respectivamente por questão de comodidade, para facilitar o entendimento do que cada um faz. Ficou assim: 

Imagem 2.2
Imagem 2.2 : MainActivity.java

Voltando ao método onCreate, escreva as linhas

sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);

    Com essas linhas, respectivamente foram instanciados o sensorManager(linha 1) e o acelerômetro(linha 2), e o acelerômetro foi registrado com um clock normal. Outras opções ao SENSOR_DELAY_NORMAL, pela ordem de velocidade são: SENSOR_DELAY_UI, SENSOR_DELAY_GAME, e SENSOR_DELAY_FASTEST. Essas opções determinam a velocidade com que o acelerômetro atualiza a leitura de seus dados. Vale lembrar que na opção fastest, dependendo do dispositivo que você está utilizando, pode resultar em travamento.

    Tendo isso feito, vá para a próxima fase do tutorial, até o momento, o arquivo MainActivity.java ficou assim:

package ufopimobilisjm.br.tutorial;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class MainActivity extends AppCompatActivity implements SensorEventListener {
Sensor accelerometer;
SensorManager sensorManager;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
    }



    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}

Recebendo os dados do acelerômetro

    Para receber os dados do acelerômetro,  vá na função onSensorChanged dentro da classe ActivityMain.java.  Tal método é chamado todas as vezes que ocorre alguma alteração, mesmo que mínima, no(s) sensor(es) que estiver(em) sendo utilizado(s). Sendo assim, tudo que estiver dentro do bloco de código do método é invocado constantemente, quase que em um loop infinito, porém com a condição de ter havido alguma alteração nos dados de algum sensor.

    Para receber os dados do acelerômetro, primeiramente declare-os da seguinte forma:

Sensor accelerometer;

e

SensorManager sensorManager;

    Escreva também as linhas :

float sensorX;
float sensorY;
float sensorZ;

    Já dentro do método onSensorChanged insira as linhas:

sensorX = event.values[0];
sensorY = event.values[1];
sensorZ = event.values[2];

   O código event.values[] com os valores 0,1 e 2 representam respectivamente as variações nos dados do sensor nos eixos X, Y e Z, fica mais claro nessa Imagem retirada do site do Android Developers:

Imagem 3.1
Imagem 3.1 : Eixos do acelerômetro

    Agora que os dados já foram obtidos, basta exibi-los na tela do seu smartphone Android. Por enquanto o código do método onSensorChanged está assim:

public void onSensorChanged(SensorEvent event) {
    sensorX = event.values[0];
    sensorY = event.values[1];
    sensorZ = event.values[2];

Exibindo na tela

    Para exibir os dados na tela do smartphone, altere o activity_main.xml. Onde são programados os objetos que aparecerão na tela durante a execução da aplicação.

A programação xml pode ser feita pela aba de Design no AndroidStudio, que é uma ferramenta muito útil e perfeitamente utilizável para a programação de um layout. Porém para tornar esse tutorial mais fácil de ser compreendido,  a programação do xml foi feita na aba de texto.

Já na aba de texto do activity_main.xml mude o código que está mostrado na imagem 1.7 para o seguinte:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:orientation="vertical">
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="X: "
        android:id="@+id/tX" />
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Y: "
        android:id="@+id/tY" >
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Z: "
        android:id="@+id/tZ" />
</LinearLayout>

    O layout de programação antigo era um RelativeLayout, que é mais facilmente programado pela aba de Design no AndroidStudio. Porém o layout LinearLayout foi escolhido para esse tutorial. No LinearLayout, os objetos adicionados vão sendo dispostos um depois do outro, como em uma fila, sem a necessidade de dizer isso para o código.

    Para ver o que aconteceu, vá na aba de layout onde será representado o que vai aparecer na tela do smartphone agora que o código acima foi adicionado ao activity_main.xml.

Ficou assim:

Imagem 4.1
Imagem 4.1 : activity_main.xml layout

    Agora ainda é preciso instanciar o que vai acontecer com esses TextView’s, e para isso volte na MainActivity.java. De volta no método onSensorChanged, abaixo das linhas onde foram instanciados os sensores X,Y e Z, adicione as linhas: 

TextView tx = (TextView) findViewById(R.id.tX);
TextView ty = (TextView) findViewById(R.id.tY);
TextView tz = (TextView) findViewById(R.id.tZ);
tx.setText("X: " + (sensorX));
ty.setText("Y: " + (sensorY));
tz.setText("Z: " + (sensorZ));

O AndroidStudio deve importar automaticamente a classe TextView,caso isso não ocorra, basta selecionar a linha onde o TextView esta escrito e apertar Alt+Enter.

Agora finalmente já é possível visualizar os dados do acelerômetro sendo exibidos na tela do dispositivo!

Imagem 4.3
Imagem 4.3: Dados do acelerômetro na tela.

Normalização dos dados

    Para facilitar a compreensão dos dados e também a visualização, junte toda essa informação que conseguimos no capítulo anterior em um lugar só. Para fazer isso, basta inserir mais algumas linhas nos códigos do main_activity.xml e ActivityMain.java.

    Primeiro, adicione esse trecho de código no activity_main.xml

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="A: "
    android:id="@+id/tA" />

    Esse trecho adiciona o Texto “A:” na tela do aparelho, agora atribua valores à esse novo texto.

    Voltando ao MainActivity.java, adicione as linhas de instanciamento do Sensor, do texto e a atribuição dos valores.

    Abaixo de:

sensorZ = event.values[2];

    Adicione a linha :

float sensorA = (event.values[0] + event.values[1] + event.values[2]);

    Essa linha no código vai somar os valores dos 3 eixos e apresenta-los dentro de uma única variável. Também é preciso declarar o TextView:

TextView ta = (TextView) findViewById(R.id.tA);

e adicionar o valor de SensorA ao texto exibido na tela :

tA.setText("A: " + (sensorA));

    Agora os códigos e a tela do aparelho ficaram assim:

public void onSensorChanged(SensorEvent event) {
    sensorX = event.values[0];
    sensorY = event.values[1];
    sensorZ = event.values[2];
    float sensorA = (event.values[0] + event.values[1] + event.values[2]);
    TextView tx = (TextView) findViewById(R.id.tX);
    TextView ty = (TextView) findViewById(R.id.tY);
    TextView tz = (TextView) findViewById(R.id.tZ);
    TextView ta = (TextView) findViewById(R.id.tA);
    tx.setText("X: " + (sensorX));
    ty.setText("Y: " + (sensorY));
    tz.setText("Z: " + (sensorZ));
    ta.setText("A: " + (sensorA));
<?xml version="1.0" encoding="utf-8"?&gt;
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:orientation="vertical">
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="X: "
        android:id="@+id/tX" />
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Y: "
        android:id="@+id/tY" />
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Z: "
        android:id="@+id/tZ" />
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="A: "
        android:id="@+id/tA" />
</LinearLayout>
Imagem 5.1
Imagem 5.1 : dados do acelerômetro normalizados adicionados

Escrevendo e salvando dentro da memória externa do Dispositivo

    O arquivo está sendo escrito na “memória externa” e não na “memória interna” pois um arquivo só pode ser acessado pela aplicação que o criou se estiver na memória externa.

Para facilitar a compreensão, crie um método chamado Escreve() que faz tudo o que será preciso para essa parte do tutorial. Após a apresentação do código abaixo será explicado linha por linha o que ele faz. Insira dentro da classe MainActivity.java o seguinte trecho de código:

OutputStreamWriter dlog;
File file;
FileOutputStream log;

public void Escreve (float sensorX, float sensorY, float sensorZ, float sensorA){

    try {
        file = Environment.getExternalStorageDirectory();
        log = new FileOutputStream(file.toString() + "/Tutorial.txt",true);
        Log.i("DROP", "nome:" + file.getPath());
        dlog = new OutputStreamWriter(log);
        dlog.append("\n" + sensorX);
        dlog.flush();
        dlog.append(";" + sensorY);
        dlog.flush();
        dlog.append(";" + sensorZ);
        dlog.flush();
        dlog.append(";" + sensorA);
        dlog.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

   Declare as novas variáveis que vamos usar, dlog,file e log. Logo após, declare o método que, linha por linha faz o seguinte, Instancia o arquivo file, nomeia o arquivo(você pode substituir “Tutorial” pelo nome que quiser), é instanciado o “escritor” e utiliza-se o dlog.append() para escrever os dados das variáveis Sensor no arquivo criado. Os “;” são apenas para separar um dado do outro no arquivo.

    Porém, para conseguirmos acesso ao “external storage” de um aparelho, é preciso mexer um pouco no AndroidManifest. Esse é o terceiro arquivo que será necessário utilizar. Então vá em App > Manifest > AndroidManifest.xml. Vai estar assim:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ufopimobilisjm.br.tutorial">
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter&gt;
              <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter&gt;
        </activity&gt;
       </application&gt;
</manifest>

 Remova a linha :

android:theme="@style/AppTheme.NoActionBar">

e a substitua por esta:

android:theme="@style/AppTheme">

    Agora adicione a permissão para escrever no “external Storage” do dispositivo, adicione as linhas:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    Estas permitem a escrita e leitura de arquivos no “external Storage” do aparelho.

    Feito isso, o AndroidManifest.xml ficou assim:

<?xml version="1.0" encoding="utf-8"?&gt;
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ufopimobilisjm.br.tutorial">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
    <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
    <intent-filter>
              <action android:name="android.intent.action.MAIN" />
             <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
          </activity>
         </application>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>

      Volte no método onSensorChanged e adicione mais algumas linhas. Pois a aplicação abriu um arquivo e agora ela tem que fechá-lo. Adicione as linhas:

try {
    dlog.close();
} catch (IOException e) {
    e.printStackTrace();
}
try {
    log.close();
} catch (IOException e) {
    e.printStackTrace();
}

no final do método.

    O código dos métodos no  arquivo MainActivity.java ficou assim:

@Override
public void onSensorChanged(SensorEvent event) {
    sensorX = event.values[0];
    sensorY = event.values[1];
    sensorZ = event.values[2];
    float sensorA = (event.values[0] + event.values[1] + event.values[2]);
    TextView tx = (TextView) findViewById(R.id.tX);
    TextView ty = (TextView) findViewById(R.id.tY);
    TextView tz = (TextView) findViewById(R.id.tZ);
    TextView ta = (TextView) findViewById(R.id.tA);
    tx.setText("X: " + (sensorX));
    ty.setText("Y: " + (sensorY));
    tz.setText("Z: " + (sensorZ));
    ta.setText("A: " + (sensorA));
    Escreve(sensorX, sensorY, sensorZ, sensorA);
    try {
        dlog.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        log.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

OutputStreamWriter dlog;
File file;
FileOutputStream log = null;

public void Escreve (float sensorX, float sensorY, float sensorZ, float sensorA){

    try {
        file = Environment.getExternalStorageDirectory();
        log = new FileOutputStream(file.toString() + "/Tutorial.txt",true);
        dlog = new OutputStreamWriter(log);
        dlog.append("\n" + sensorX);
        dlog.flush();
        dlog.append(";" + sensorY);
        dlog.flush();
        dlog.append(";" + sensorZ);
        dlog.flush();
        dlog.append(";" + sensorA);
        dlog.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

Encontrando o arquivo na memória

    Não é possível encontrar o arquivo pelo File Explorer nativo do aparelho. Para fazer isso, baixe o aplicativo “EsFileExplorer” na PlayStore.

    Instalado o aplicativo, vamos encontrá-lo:

Abra o EsFileExplorer :

Imagem 7.1
Imagem 7.1 : Tela inicial do “EsFileExplorer”

    Clique no botão de procura, é uma lupa do lado de onde está escrito “Homepage” e digite o nome do seu arquivo, nesse caso, “Tutorial”.

Imagem 7.2
Imagem 7.2 : Imagem do Tutorial.txt

    O arquivo vai ficar assim:

Imagem 7.3
Imagem 7.3 : Arquivo Tutorial.txt

Dúvidas? Entre em contato comigo: moc.liamtohnull@32noimsolrac

 

 

Summary
Tutorial Android - Obtendo os dados do acelerômetro no Android
Article Name
Tutorial Android - Obtendo os dados do acelerômetro no Android
Description
Tutorial Android - Obtendo os dados do acelerômetro no Android
Author
Publisher Name
iMobilis
Publisher Logo

3 Responses to “Tutorial Android – Entendendo e obtendo os dados do acelerômetro no Android”

Trackbacks & Pings

Deixe um comentário

O seu endereço de e-mail não será publicado.