Failed to getWritableDatabase (); Android

1

It gives me a mistake when it comes to establishing the database as writable in this line:

SQLiteDatabase db = baseDatos.getWritableDatabase();

Android Monitor ERROR:

FATAL EXCEPTION: main
                                                                         Process: com.example.iberd.actionvalue, PID: 1918                                                              java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.iberd.actionvalue/com.example.iberd.actionvalue.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase com.example.iberd.actionvalue.sqlite.BaseDatosValue.getWritableDatabase()' on a null object reference
                                                                             at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                                                                             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                                                                             at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                             at android.os.Looper.loop(Looper.java:154)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                                          Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase com.example.iberd.actionvalue.sqlite.BaseDatosValue.getWritableDatabase()' on a null object reference
                                                                             at com.example.iberd.actionvalue.sqlite.OperacionesBaseDatos.getDb(OperacionesBaseDatos.java:36)
                                                                             at com.example.iberd.actionvalue.MainActivity.onCreate(MainActivity.java:70)
                                                                             at android.app.Activity.performCreate(Activity.java:6679)
                                                                             at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                             at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                                                                             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
                                                                             at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                                             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
                                                                             at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                             at android.os.Looper.loop(Looper.java:154) 
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                                             at java.lang.reflect.Method.invoke(Native Method)

In the Main class, I add the elements to the object and overload the method insertarCartera() of the class OperationsDatabase:

 public class MainActivity extends AppCompatActivity {

OperacionesBaseDatos bdOperaciones = new OperacionesBaseDatos();

// Agregamos un método en MainActivity, los métodos para obtener una instancia de la misma y sea y usado como contexto:
 public static MainActivity thisActivity;

 public MainActivity() {
 thisActivity = this;
 }

 public static MainActivity getInstance() {
 return thisActivity;
 }

static final String[] TITULOS_BTN =
        new String[]{"INTEL (INTC)", "PFIZER (PFE)", "CISCO (CSCO)", "GENERAL ELECTRIC (GE)",
                "ORACLE (ORCL)", "SUNWORKS (SUNW)", "IBM (IBM)", "HP (HPQ)", "QUALCOMM (QCOM)",
                "AMAZON (AMZN)", "MICROSOFT (MSFT)", "APPLE (AAPL)", "NASDAQ (NDAQ)", "ORO (GC=F)", "PETROLEO (CL=F)"};

public ListView lvListaDeBotones;

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

    lvListaDeBotones = (ListView) findViewById(R.id.lvListaDeBotones);
    MyAdapter mAdapter = new MyAdapter(this, TITULOS_BTN);
    lvListaDeBotones.setAdapter(mAdapter);

    //Puede que sobre
    lvListaDeBotones.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // Aquí puedes capturar en on Click de la vista que se crea en general.
        }
    });

    Button btnIbex = (Button) findViewById(R.id.noticiasButton);

    btnIbex.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(v.getContext(), bdPruebaActivity.class);
            startActivity(intent);
        }
    });


     Cartera carteraObj = new Cartera();
     carteraObj.setId_valor(4);
     carteraObj.setPrecio(Float.valueOf(String.valueOf(7777.77)));
     carteraObj.setFcompra("2017-02-12 12:12:12.475");
     carteraObj.setCantidad(7);

     bdOperaciones.insertarCartera(carteraObj);

}
}

Class OperationsDatabase:

public class OperacionesBaseDatos {

private static BaseDatosValue baseDatos;
private static OperacionesBaseDatos instancia;

public static OperacionesBaseDatos obtenerInstancia() {
    return obtenerInstancia(MainActivity.getInstance());
}

public static OperacionesBaseDatos obtenerInstancia(Context contexto) {
    if (baseDatos == null) {
        baseDatos = new BaseDatosValue(contexto);
    }
    return instancia;
}

public void insertarCartera(Cartera cartera) {
    SQLiteDatabase db = baseDatos.getWritableDatabase();

    ContentValues valores = new ContentValues();
    valores.put(MetadatosDB.Carteras.ID_VALOR, cartera.getId_valor());
    valores.put(MetadatosDB.Carteras.PRECIO, cartera.getPrecio());
    valores.put(MetadatosDB.Carteras.FCOMPRA, cartera.getFcompra());
    valores.put(MetadatosDB.Carteras.CANTIDAD, cartera.getCantidad());

    db.insertOrThrow(BaseDatosValue.Tablas.CARTERA, null, valores);

    db.close();
}
}
    
asked by Eduardo 19.05.2017 в 13:33
source

4 answers

1

As it is currently your code, it is necessary to use the method that receives the context to obtain the instance of the DB:

OperacionesBaseDatos bdOperaciones = new OperacionesBaseDatos(getApplicationContext());

What is done in this case to ensure obtaining an instance of the database when calling a method that does not receive the context, is to add a method in MainActivity the methods to obtain an instance of it and be used as a context:

public static MainActivity thisActivity;

public MainActivity() {
    thisActivity = this;
}

public static MainActivity getInstance() {
    return thisActivity;
}

This to ensure that both methods work and get the instance of the DB:

public static OperacionesBaseDatos obtenerInstancia() {
   return obtenerInstancia(MainActivity.getIntance());
}

public static OperacionesBaseDatos obtenerInstancia(Context contexto) {
    if (baseDatos == null) {
        baseDatos = new BaseDatosValue(contexto);
    }
    return instancia;
}

in this way you can easily do what you want:

OperacionesBaseDatos bdOperaciones = new OperacionesBaseDatos();
    
answered by 19.05.2017 / 18:41
source
1

The variable baseDatos is never initialized. For this you can put in the constructor this:

public OperacionesBaseDatos(Context contexto) {
    if (baseDatos == null) {
        baseDatos = new BaseDatosValue(contexto);
    }
    return instancia;
}

At the time of initializing the class do the following:

OperacionesBaseDatos bdOperaciones = new OperacionesBaseDatos(getApplicationContext());
    
answered by 19.05.2017 в 13:42
1

The error is that you are initializing OperacionesBaseDatos through the constructor instead of the instance then baseDatos is null, to initialize it:

Context contexto = this; // Si estás en un Activity
OperacionesBaseDatos bdOperaciones = OperacionesBaseDatos.obtenerInstancia(contexto);

When using the Singleton pattern the constructor is usually made private since it should only be accessible through the class itself using the method that the instance obtains.

To get the context, if you are in an Activity you can use this (the Activity itself), if you are in a Fragment you can pass the Activity with getActivity() . If you are in a class you must pass it to them through the method from the place where you call it

    
answered by 19.05.2017 в 13:40
1

Eye, your constructor receives a Context as parameter and you do not send it, therefore your object BaseDatosValue is not initialized at any time.

When you call your database you should send it, if you are from Activity

OperacionesBaseDatos bdOperaciones = new OperacionesBaseDatos(getContext());
bdOperaciones.insertarCartera(carteraObj);
    
answered by 19.05.2017 в 15:09