Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

18
respostas

Camera parou.

Erros ao fim da aula 2 com relação a câmera (no vídeo 1, que é só a criação de design tudo funcionou. No vídeo 2 aonde as funções do botão são implementadas e você pode tirar a foto de fato, só ao registrar a foto o apk parava de funcionar, a partir do vídeo 3 aonde a foto é salva na memoria, o apk nem executa mais e o emulador já abre dizendo que a agenda crashou se deseja abrir novamente. PS: Já segui as devidas correções e adaptações pro Android 7 e atualmente estou no Android 8 em minha maquina virtual.

Logcat:

Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
at android.database.CursorWindow.nativeGetString(Native Method)
at android.database.CursorWindow.getString(CursorWindow.java:438)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
at com.tales.agenda.DAO.AlunoDAO.buscaAlunos(AlunoDAO.java:78)
at com.tales.agenda.ListaAlunosActivity.carregaLista(ListaAlunosActivity.java:62)
at com.tales.agenda.ListaAlunosActivity.onResume(ListaAlunosActivity.java:72) 
...                                                      
Linha relacionada ao AlunoDAO java 78:
aluno.setFoto(c.getString(c.getColumnIndex("caminhoFoto")));

Relacionado ao ListaAlunos java 62:
AlunoDAO dao = new AlunoDAO(this);
        List<Aluno> alunos = dao.buscaAlunos();

Relacionado ao ListaAlunos 72:
carregaLista();

Codigo do AlunoDAO:
public class AlunoDAO extends SQLiteOpenHelper {
    public AlunoDAO (Context context) {
        super(context, "Agenda", null, 1);
    }
    @Override
    public void onCreate (SQLiteDatabase db) {
        String sql = "CREATE TABLE Alunos (id INTEGER PRIMARY KEY, nome TEXT NOT NULL, endereco TEXT, telefone TEXT, site TEXT, nota REAL, caminhoFoto TEXT);";
        db.execSQL(sql);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String sql = "";
        switch (oldVersion){
            case 1:
                sql = "ALTER TABLE Alunos ADD COLUMN caminhoFoto TEXT";
        }
        db.execSQL(sql);
    }
    public void insert(Aluno aluno)  {
        SQLiteDatabase db = getWritableDatabase();
        ContentValues dados = pegaDadosAluno(aluno);
        db.insert("Alunos", null, dados );
    }
    @NonNull
    private ContentValues pegaDadosAluno(Aluno aluno) {
        ContentValues dados = new ContentValues();
        dados.put("nome", aluno.getNome());
        dados.put("endereco", aluno.getEndereco());
        dados.put("telefone", aluno.getTelefone());
        dados.put("site", aluno.getSite());
        dados.put("nota", aluno.getNota());
        dados.put("caminhoFoto", aluno.getFoto());
        return dados;
    }
    public List<Aluno> buscaAlunos() {
        String sql = "SELECT * FROM Alunos;";
        SQLiteDatabase db = getReadableDatabase();
        Cursor c = db.rawQuery(sql, null);
        List<Aluno> alunos = new ArrayList<Aluno>();
        while (c.moveToNext()) {
            Aluno aluno = new Aluno();
            aluno.setId(c.getLong(c.getColumnIndex("id")));
            aluno.setNome(c.getString(c.getColumnIndex("nome")));
            aluno.setEndereco(c.getString(c.getColumnIndex("endereco")));
            aluno.setTelefone(c.getString(c.getColumnIndex("telefone")));
            aluno.setSite(c.getString(c.getColumnIndex("site")));
            aluno.setNota(c.getDouble(c.getColumnIndex("nota")));
            aluno.setFoto(c.getString(c.getColumnIndex("caminhoFoto")));

            alunos.add(aluno);
        }
        //fecha conexao com o banco de dados
        c.close();
        //retorna os alunos colhidos
        return alunos;
    }
    public void delet(Aluno aluno) {
        SQLiteDatabase db = getWritableDatabase();
        String [] params = {String.valueOf(aluno.getId())};injection passando uma lista de parametros por string
        db.delete("Alunos", "id = ?", params);
    }
    public void alter(Aluno aluno) {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues dados = pegaDadosAluno(aluno);

        String[] params ={aluno.getId().toString()};
        db.update("Alunos", dados, "id = ?", params);
    }
}
18 respostas

Codigo Lista Alunos:

public class ListaAlunosActivity extends AppCompatActivity {
    private ListView listaAlunos;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lista_alunos);


        listaAlunos = (ListView) findViewById(R.id.lista_alunos_listaAlunos);

        listaAlunos.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> lista, View item, int posicao, long id) {
                Aluno aluno = (Aluno) listaAlunos.getItemAtPosition(posicao);

                Intent vaiProFormulario = new Intent(ListaAlunosActivity.this, FormularioActivity.class);
                vaiProFormulario.putExtra("aluno", aluno);
                startActivity(vaiProFormulario);
            }
        });

        Button novoAluno = (Button) findViewById(R.id.lista_alunos_novoAluno);
        novoAluno.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                Intent vaiProFormulario = new Intent(ListaAlunosActivity.this,FormularioActivity.class);
                startActivity(vaiProFormulario);
            }
        });

        registerForContextMenu(listaAlunos);
    }

    private void carregaLista()  {
        AlunoDAO dao = new AlunoDAO(this);
        List<Aluno> alunos = dao.buscaAlunos(); dao.close();

        listaAlunos = (ListView)  findViewById(R.id.lista_alunos_listaAlunos);
        ArrayAdapter<Aluno> adapter = new ArrayAdapter<Aluno>(this,  android.R.layout.simple_list_item_1, alunos);
        listaAlunos.setAdapter(adapter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        carregaLista();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, final ContextMenu.ContextMenuInfo menuInfo) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;

        final Aluno aluno = (Aluno) listaAlunos.getItemAtPosition(info.position);

        MenuItem itemLigar = menu.add("Ligar para " + aluno.getNome());
        itemLigar.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                if (ActivityCompat.checkSelfPermission(ListaAlunosActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(ListaAlunosActivity.this,
                            new String[]{Manifest.permission.CALL_PHONE}, 123);
                } else {
                    Intent intentLigar = new Intent(Intent.ACTION_CALL);
                    intentLigar.setData(Uri.parse("tel:" + aluno.getTelefone()));
                    startActivity(intentLigar);
                }
                return false;
            }
        });

        MenuItem itemSMS = menu.add("Enviar SMS para " + aluno.getNome());
        Intent intentSMS = new Intent(Intent.ACTION_VIEW);

        intentSMS.setData(Uri.parse("sms:" + aluno.getTelefone()));
        itemSMS.setIntent(intentSMS);

        MenuItem itemMapa = menu.add("Visualizar " + aluno.getNome() + " no Mapa");
        Intent intentMapa = new Intent(Intent.ACTION_VIEW);

        intentMapa.setData(Uri.parse("geo:0,0?q=" + aluno.getEndereco()));
        itemMapa.setIntent(intentMapa);

        MenuItem itemSite = menu.add("Visitar Site do(a) " + aluno.getNome());
        Intent intentSite = new Intent(Intent.ACTION_VIEW);

        String site = aluno.getSite();
        if (!site.startsWith("http://")){
            site = "http://" + site;
        }

        intentSite.setData(Uri.parse(site));
        itemSite.setIntent(intentSite);

        MenuItem deletar = menu.add("Deletar "  + aluno.getNome());
        deletar.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                AlunoDAO dao = new AlunoDAO(ListaAlunosActivity.this);
                dao.delet(aluno);
                dao.close();

                carregaLista();
                return false;
            }
        });
    }
}

Codigo Helper

public class FormularioHelper {
    private final EditText campoNome;
    private final EditText campoEndereco;
    private final EditText campoTelefone;
    private final EditText campoSite;
    private final RatingBar campoNota;
    private final ImageView campoFoto;

    private Aluno aluno;
    public FormularioHelper(FormularioActivity activity) {
        campoNome = (EditText) activity.findViewById(R.id.formulario_nome);
        campoEndereco = (EditText) activity.findViewById(R.id.formulario_endereco);
        campoTelefone = (EditText) activity.findViewById(R.id.formulario_telefone);
        campoSite = (EditText) activity.findViewById(R.id.formulario_site);
        campoNota = (RatingBar) activity.findViewById(R.id.formulario_nota);
        campoFoto = (ImageView) activity.findViewById(R.id.formulario_foto);
        aluno = new Aluno();
    }

    public Aluno pegaAluno() {
        aluno.setNome(campoNome.getText().toString());
        aluno.setEndereco(campoEndereco.getText().toString());
        aluno.setTelefone(campoTelefone.getText().toString());
        aluno.setSite(campoSite.getText().toString());
        aluno.setNota(Double.valueOf(campoNota.getProgress()));
        aluno.setFoto((String) campoFoto.getTag());
        return aluno;
    }

    public void preencheFormulario(Aluno aluno)  {
        campoNome.setText(aluno.getNome());
        campoEndereco.setText(aluno.getEndereco());
        campoTelefone.setText(aluno.getTelefone());
        campoSite.setText(aluno.getSite());
        campoNota.setProgress(aluno.getNota().intValue());
        carregaImagem(aluno.getFoto());
        this.aluno = aluno;
    }

    public void carregaImagem(String caminhoFoto) {
        if (caminhoFoto != null){
            Bitmap bitmap = BitmapFactory.decodeFile(caminhoFoto);
            Bitmap bitmapReduzido = Bitmap.createScaledBitmap(bitmap, 300,300,true);
            campoFoto.setImageBitmap(bitmapReduzido);
            campoFoto.setScaleType(ImageView.ScaleType.FIT_XY);
            campoFoto.setTag(caminhoFoto);
        }
    }
}

Codigo Aluno

public class Aluno implements Serializable {
    private Long id;
    private String nome;
    private String endereco;
    private String telefone;
    private String site;
    private Double nota;
    private String foto;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getEndereco() {
        return endereco;
    }

    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }

    public String getSite() {
        return site;
    }

    public void setSite(String site) {
        this.site = site;
    }

    public Double getNota() {
        return nota;
    }

    public void setNota(Double nota) {
        this.nota = nota;
    }

    public String getFoto() {
        return foto;
    }

    public void setFoto(String foto) {
        this.foto = foto;
    }
string
    @Override
    public String toString()  {
        return getId() + " - " + getNome();
    }
}

Codigo Formulario Activity:

public class FormularioActivity extends AppCompatActivity {

    public static final int CODIGO_CAMERA = 567;
    private FormularioHelper helper;
    private String caminhoFoto;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_formulario);

        helper = new FormularioHelper(this);

        Intent intent = getIntent();
        Aluno aluno = (Aluno) intent.getSerializableExtra("aluno");
        if (aluno.getId() != null){
            helper.preencheFormulario(aluno);
        }
        Button botaoFoto = (Button) findViewById(R.id.formulario_botao_foto);
        botaoFoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                caminhoFoto = getExternalFilesDir(null) + "/" + System.currentTimeMillis() + ".jpg";
                File arquivoFoto = new File(caminhoFoto);
                intentCamera.putExtra(MediaStore.EXTRA_OUTPUT,
                        FileProvider.getUriForFile(FormularioActivity.this,
                                BuildConfig.APPLICATION_ID + ".provider", arquivoFoto));
                startActivityForResult(intentCamera, CODIGO_CAMERA);
            }
        });
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == Activity.RESULT_OK){
            if (requestCode == CODIGO_CAMERA){
                helper.carregaImagem(caminhoFoto);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_formulario, menu);
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
            case R.id.menu_formulario_ok:
                Aluno aluno = helper.pegaAluno();

                AlunoDAO dao = new AlunoDAO(this);
                if (aluno.getId() != null){
                    dao.alter(aluno);
                } else {
                    dao.insert(aluno);
                }
                dao.close();
                Toast.makeText(FormularioActivity.this, "Aluno " + aluno.getNome() + " salvo!", Toast.LENGTH_SHORT).show();

                finish();
                break;
        }
        return super.onOptionsItemSelected(item);
    }
}

Fala ai Tales, de boa ?

Cara vi que a versão do seu banco tá na 1, imagino que tenha esquecido de evoluir a versão, tenta colocar a depois e vê o que rola.

Fala Matheus, eu notei isso pouco depois (não atualizei aqui) mas atualizei no programa e ele permaneceu dando erro

Consegue me mostrar exatamente a exception para podermos ver ?

Vou executar o projeto de novo e já mando a exception que aparecer, vou fazer uma execução limpa, com uma maquina virtual nova

03-26 17:01:28.525 5239-5239/com.tales.agenda E/AndroidRuntime: FATAL EXCEPTION: main
                                                                Process: com.tales.agenda, PID: 5239
                                                                java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tales.agenda/com.tales.agenda.FormularioActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Long com.tales.agenda.Model.Aluno.getId()' on a null object reference
                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
                                                                    at android.app.ActivityThread.-wrap11(Unknown Source:0)
                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
                                                                    at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                    at android.os.Looper.loop(Looper.java:164)
                                                                    at android.app.ActivityThread.main(ActivityThread.java:6494)
                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
                                                                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Long com.tales.agenda.Model.Aluno.getId()' on a null object reference
                                                                    at com.tales.agenda.FormularioActivity.onCreate(FormularioActivity.java:50)
                                                                    at android.app.Activity.performCreate(Activity.java:7009)
                                                                    at android.app.Activity.performCreate(Activity.java:7000)
                                                                    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)

Tales,

Se não chegar um aluno, você não consegue fazer algo com ele :(

  if (aluno.getId() != null){
            helper.preencheFormulario(aluno);
        }

Nesse código você pode ter um aluno como não pode, o que eu sugiro fazer é :

  if (aluno  != null){
            helper.preencheFormulario(aluno);
        }

Putz cara, funcionou ele começando a funcionar só não ta salvando agora no contato

Ele tá gerando alguma exception ? Ou só não está salvando mesmo ?

Nenhuma Exception.

Tales, faz o seguinte:

  • desinstala o aplicativo e tenta executar novamente, nesse momento fica atento no logcat(console) quando você tentar fazer uma inserção e fala o que aconteceu por gentileza
03-27 18:42:00.472 6727-6727/? I/zygote: Not late-enabling -Xcheck:jni (already on)
03-27 18:42:00.486 6727-6727/? W/zygote: Unexpected CPU variant for X86 using defaults: x86
03-27 18:42:00.823 6727-6727/? I/InstantRun: starting instant run server: is main process
03-27 18:42:01.151 6727-6747/? D/OpenGLRenderer: HWUI GL Pipeline
03-27 18:42:01.188 6727-6747/? I/zygote: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
03-27 18:42:01.189 6727-6747/? I/OpenGLRenderer: Initialized EGL, version 1.4
03-27 18:42:01.189 6727-6747/? D/OpenGLRenderer: Swap behavior 1
03-27 18:42:01.189 6727-6747/? W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
03-27 18:42:01.189 6727-6747/? D/OpenGLRenderer: Swap behavior 0
03-27 18:42:01.198 6727-6747/? D/EGL_emulation: eglCreateContext: 0x9cf07440: maj 3 min 0 rcv 3
03-27 18:42:01.253 6727-6747/? D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:01.358 6727-6747/? D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:21.349 6727-6747/com.tales.agenda D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:21.393 6727-6732/com.tales.agenda I/zygote: Do partial code cache collection, code=18KB, data=23KB
03-27 18:42:21.393 6727-6732/com.tales.agenda I/zygote: After code cache collection, code=18KB, data=23KB
03-27 18:42:21.393 6727-6732/com.tales.agenda I/zygote: Increasing code cache capacity to 128KB
03-27 18:42:21.394 6727-6732/com.tales.agenda I/zygote: Do partial code cache collection, code=18KB, data=40KB
03-27 18:42:21.394 6727-6732/com.tales.agenda I/zygote: After code cache collection, code=18KB, data=40KB
03-27 18:42:21.394 6727-6732/com.tales.agenda I/zygote: Increasing code cache capacity to 256KB
03-27 18:42:21.394 6727-6732/com.tales.agenda I/zygote: JIT allocated 71KB for compiled code of void android.widget.TextView.<init>(android.content.Context, android.util.AttributeSet, int, int)
03-27 18:42:21.394 6727-6732/com.tales.agenda I/zygote: Compiler allocated 4MB to compile void android.widget.TextView.<init>(android.content.Context, android.util.AttributeSet, int, int)
03-27 18:42:21.484 6727-6727/com.tales.agenda V/View: dispatchProvideAutofillStructure(): not laid out, ignoring 0 children of 1073741835
03-27 18:42:21.491 6727-6727/com.tales.agenda I/AssistStructure: Flattened final assist data: 3656 bytes, containing 1 windows, 13 views
03-27 18:42:25.231 6727-6747/com.tales.agenda D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:30.265 6727-6747/com.tales.agenda D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:30.799 6727-6732/com.tales.agenda I/zygote: Do full code cache collection, code=122KB, data=90KB
03-27 18:42:30.799 6727-6732/com.tales.agenda I/zygote: After code cache collection, code=113KB, data=67KB
03-27 18:42:41.206 6727-6747/com.tales.agenda D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:41.218 6727-6747/com.tales.agenda D/EGL_emulation: eglMakeCurrent: 0x9cf07440: ver 3 0 (tinfo 0xa4d9b4f0)
03-27 18:42:41.263 6727-6732/com.tales.agenda I/zygote: Do partial code cache collection, code=124KB, data=77KB
03-27 18:42:41.263 6727-6732/com.tales.agenda I/zygote: After code cache collection, code=124KB, data=77KB
03-27 18:42:41.263 6727-6732/com.tales.agenda I/zygote: Increasing code cache capacity to 512KB

Tales, não identifiquei nenhum problema :(

Quer me passar o código via github ? Que dessa forma rodo e debugo o sistema para você ?

não possuo GitHub, segue o link para baixar o projeto pelo drive, no aguardo de informações https://drive.google.com/drive/folders/1PHObwGS-n-EcwpuAL59tjuUqLztUeV2x?usp=sharing

Deu em algo, Matheus?

Tales

Funcionou tive que fazer uma pequena alteração no seu código:


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK){
            if (requestCode == CODIGO_CAMERA){
                helper.carregaImagem(caminhoFoto);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

De restante funcionou sem problemas. Imagino que você tenha se enrolado no momento de alterar as versões e não deve ter funcionado corretamente :(