Вопрос

Pretty bad to see that I developed my first app and the beta version failed to run on device. The app will basically add a picture along with text details for the same. A voice record to keep some more lively info for the same. On emulator, this is working fine, but failing on the device :-( Please help.

here is LogCat:

    06-19 18:04:33.495: E/SQLiteDatabase(31541): close() was never explicitly called on database '/data/data/com.example.tg_db1/databases/Bengalooru' 
    06-19 18:04:33.495: E/SQLiteDatabase(31541): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:2063)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1117)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1074)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1161)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:869)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:228)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at com.example.tg_db1.RegistrationAdapter.write(RegistrationAdapter.java:27)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at com.example.tg_db1.RegistrationAdapter.queryName(RegistrationAdapter.java:68)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at com.example.tg_db1.MainActivity.onCreate(MainActivity.java:50)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.Activity.performCreate(Activity.java:4533)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.ActivityThread.access$600(ActivityThread.java:128)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.os.Handler.dispatchMessage(Handler.java:99)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.os.Looper.loop(Looper.java:137)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at android.app.ActivityThread.main(ActivityThread.java:4517)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at java.lang.reflect.Method.invokeNative(Native Method)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at java.lang.reflect.Method.invoke(Method.java:511)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
    06-19 18:04:33.495: E/SQLiteDatabase(31541):    at dalvik.system.NativeStart.main(Native Method)
    06-19 18:04:33.495: E/System(31541): Uncaught exception thrown by finalizer
    06-19 18:04:33.495: E/System(31541): java.lang.IllegalStateException: Don't have database lock!
    06-19 18:04:33.495: E/System(31541):    at android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2221)
    06-19 18:04:33.495: E/System(31541):    at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2313)
    06-19 18:04:33.495: E/System(31541):    at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2309)
    06-19 18:04:33.495: E/System(31541):    at android.util.LruCache.trimToSize(LruCache.java:197)
    06-19 18:04:33.495: E/System(31541):    at android.util.LruCache.evictAll(LruCache.java:285)
    06-19 18:04:33.495: E/System(31541):    at android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements(SQLiteDatabase.java:2274)
    06-19 18:04:33.495: E/System(31541):    at android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1246)
    06-19 18:04:33.495: E/System(31541):    at android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:2034)
    06-19 18:04:33.495: E/System(31541):    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:185)
    06-19 18:04:33.495: E/System(31541):    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
    06-19 18:04:33.495: E/System(31541):    at java.lang.Thread.run(Thread.java:856)

add_company.java

    package com.example.tg_db1;

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import android.app.Activity;
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.media.MediaPlayer;
    import android.media.MediaRecorder;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.MediaStore;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageButton;
    import android.widget.ImageView;
    import android.widget.Toast;

    public class add_company extends Activity{
        ImageView iv;
        Button b1,b2,b3;
        EditText et1, et2;
        RegistrationAdapter adapter;
        RegistrationOpenHelper helper;

        private static final int REQUEST_CODE = 1;
        private String logopath;
        String imgPath = null;
        private Bitmap bitmap;

        //Adding for voice record
        ImageButton play,record,stop;
        private String voicerec=null;
        MediaPlayer mp;
        MediaRecorder mr;

        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.add_company);

            iv = (ImageView)findViewById(R.id.imageView1);
            b1 = (Button)findViewById(R.id.button1);
            b2 = (Button)findViewById(R.id.button2);
            b3 = (Button)findViewById(R.id.button3);
            et1 = (EditText)findViewById(R.id.editText1);
            et2 = (EditText)findViewById(R.id.editText2);

            adapter = new RegistrationAdapter(this);
            iv.setImageDrawable(null);  //Should be blank before selecting the image

            //Adding voice record
            play = (ImageButton)findViewById(R.id.Play);
            record = (ImageButton)findViewById(R.id.Record);
            stop = (ImageButton)findViewById(R.id.Stop);
        }

        public void browse(View v){
            @SuppressWarnings("unused")
            int id = v.getId();
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            startActivityForResult(intent, REQUEST_CODE);
        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            InputStream stream = null;

            if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {

                Uri imgUri = data.getData();
                logopath = getPath(imgUri);

                //This block is to show the view
                    try {
                        if(bitmap != null){
                            bitmap.recycle();
                        }
                            stream = getContentResolver().openInputStream(data.getData());
                            bitmap = BitmapFactory.decodeStream(stream);
                            iv.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 150, 150, true));
                        } 
                    catch (FileNotFoundException e) {
                            e.printStackTrace();
                    }
                finally{
                    if (stream != null) {
                        try {
                                stream.close();
                            } 
                        catch (Exception e) {
                                e.printStackTrace();
                        }
                    }
                }

            }
        }

        private String getPath(Uri uri) {
            String[] projection = {MediaStore.Images.Media.DATA};
            @SuppressWarnings("deprecation")
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            int col_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(col_index);
        }

        //Adding for voice record
        @SuppressWarnings("unused")
        public void submit(View v){
            String compname = et1.getText().toString();
            String address = et2.getText().toString();
            logopath = imgFilePath();
            long val = adapter.insertDetails(compname, address, logopath, voicerec);
            finish();
        }

        private String imgFilePath() {
            File imgFile = null;
            try {
                imgFile = File.createTempFile("complogo", ".png");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            FileOutputStream fOut = null;
            try {
                fOut = new FileOutputStream(imgFile);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
            imgPath = imgFile.getAbsolutePath();
            return imgPath;
        }

        public void reset(View v){
            et1.setText("");
            et2.setText("");
            iv.setImageDrawable(null);  //Image is removed when reset
            voicerec = null;    //Voice record path set to null
        }

        public void record(View v){
            File audioFile = null;
            try {
                audioFile = File.createTempFile("voice", ".amr");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            mr = new MediaRecorder();

            voicerec = audioFile.getAbsolutePath();
            //System.out.println("Path: "+voicerec);

            mr.setAudioSource(MediaRecorder.AudioSource.MIC);
            mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mr.setOutputFile(voicerec);
            try{
                mr.prepare();
            }
            catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
            Toast.makeText(add_company.this, "Recording", Toast.LENGTH_LONG).show();
            mr.start();
        }
        public void stop(View v){
            mr.stop();  //this is stop recording

            Toast.makeText(add_company.this, "Stopped", Toast.LENGTH_LONG).show();
            mr.reset();     // this is required to avoid the error:  Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1)
            mr.release();
        }
        public void play(View v){
            try{
                File f = new File(voicerec);
                Uri u = Uri.fromFile(f);
                mp = MediaPlayer.create(add_company.this, u);
                mp.setLooping(false);
                mp.start();
            }
            catch(RuntimeException re){
                re.printStackTrace();
            }
        }

    }

RegistrationAdapter.java

    package com.example.tg_db1;

    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;

    public class RegistrationAdapter {
        SQLiteDatabase sdb;
        RegistrationOpenHelper helper;
        Context context;

        public RegistrationAdapter(Context c){
            context = c;
        }

        @SuppressWarnings("static-access")
        public RegistrationAdapter read(){
            helper = new RegistrationOpenHelper(context, helper.DATABASE_NAME, null, helper.VERSION);
            sdb = helper.getReadableDatabase();
            return this;
        }

        @SuppressWarnings("static-access")
        public RegistrationAdapter write(){
            helper = new RegistrationOpenHelper(context, helper.DATABASE_NAME, null, helper.VERSION);
            sdb = helper.getWritableDatabase();
            return this;
        }

        public void close(){
            if(sdb!=null)
            sdb.close();
        }


    //Addition for voice    
        @SuppressWarnings("static-access")
        public long insertDetails(String compname, String address, String complogo, String voicerec){
            ContentValues cv = new ContentValues(); 
            cv.put(helper.COMP_NAME, compname);
            cv.put(helper.COMP_ADDRESS, address);
            cv.put(helper.COMP_LOGO, complogo);
            cv.put(helper.COMP_VOICE, voicerec);
            write();
            long val = sdb.insert(helper.TABLE_NAME, null, cv);
            close();
            return val;
        }

        @SuppressWarnings("static-access")
        public long updateDetail(int rowID, String compname, String address, String complogo, String voicerec){
            ContentValues cv = new ContentValues(); 
            cv.put(helper.COMP_NAME, compname);
            cv.put(helper.COMP_ADDRESS, address);
            cv.put(helper.COMP_LOGO, complogo);
            cv.put(helper.COMP_VOICE, voicerec);
            write();
            long val = sdb.update(helper.TABLE_NAME, cv, helper.KEY_ID + "=" + rowID, null);
            close();
            return val;
        }


        @SuppressWarnings("static-access")
        public Cursor queryName(){
            String[] cols = {helper.KEY_ID, helper.COMP_NAME, helper.COMP_ADDRESS, helper.COMP_LOGO, helper.COMP_VOICE};
            write();
            Cursor c = sdb.query(helper.TABLE_NAME, cols, null, null, null, null, null);
            return c;       
        }

        @SuppressWarnings("static-access")
        public Cursor queryAll(int nameID){
            String[] cols = {helper.KEY_ID, helper.COMP_NAME, helper.COMP_ADDRESS, helper.COMP_LOGO, helper.COMP_VOICE};
            write();
            Cursor c = sdb.query(helper.TABLE_NAME, cols, helper.KEY_ID + " = " + nameID, null, null, null, null);
            return c;
        }

        public int deleteDetail(int rowID){
            write();
            @SuppressWarnings("static-access")
            int val = sdb.delete(helper.TABLE_NAME, helper.KEY_ID + "=" + rowID, null);
            close();
            return val;
        }

    }
Это было полезно?

Решение

Try adding this to your code

    protected void onDestroy() {
    super.onDestroy();
    if (sdb!= null) {
        sdb.close();
    }

and also close the Cursor object after using it.

Hope it helps :)

Другие советы

Open the Database once in your Application class in onCreate and don't close it but close the cursor as soon as you don't need them. Keep a static reference (your sdb variable, for example) there and access it directly.

For example: RegistrationAdapter.queryName() returns a cursor. So where ever you return a cursor, check the usage and close it as soon as it is not used anymore. That should fix the issue.

Following methods are creating problems.

@SuppressWarnings("static-access")
public Cursor queryName(){
    String[] cols = {helper.KEY_ID, helper.COMP_NAME, helper.COMP_ADDRESS, helper.COMP_LOGO, helper.COMP_VOICE};
    write();
    Cursor c = sdb.query(helper.TABLE_NAME, cols, null, null, null, null, null);
    return c;       
}

    @SuppressWarnings("static-access")
    public Cursor queryAll(int nameID){
        String[] cols = {helper.KEY_ID, helper.COMP_NAME, helper.COMP_ADDRESS, helper.COMP_LOGO, helper.COMP_VOICE};
        write();
        Cursor c = sdb.query(helper.TABLE_NAME, cols, helper.KEY_ID + " = " + nameID, null, null, null, null);
        return c;
    }

close your database and cursor you are returning after you use them.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top