Android数据库可供所有活动读取

时间:2017-07-04 20:36:43

标签: android sqlite android-fragments sqliteopenhelper

更新:我需要覆盖onDestroy方法来关闭Database Helper类对象。现在工作正常。只需在创建SQLiteOpenHelper类对象的任何活动中添加它。

Database dbHelper; //in class
dbHelper = new Database(this, "pulling data",null,1); //in onCreate

@Override
protected void onDestroy()
{
    super.onDestroy();
    dbHelper.close();
}

我从一个片段创建和更新数据库,其数据大约每2秒从通过蓝牙连接到我的Android应用程序的传感器进入。

我在我的应用程序中进行了不同的活动,这些活动应该能够从数据库中读取以在列表/文本视图中显示数据,但问题是创建数据库并且正在更新的上下文是从一个片段。有没有办法让所有活动都可以从数据库中读取?

我创建了一个扩展SQLiteOpenHelper的类,您可以在其中访问函数来执行CRUD操作,但是一旦我进入另一个活动并且我查询数据库,光标就没有任何内容,尽管我插入并在后台更新数据库一个片段。

抬头,我是Android开发人员的新手并且已经查看了其他问题/解决方案,但对我来说没有任何作用。感谢任何教程或建议,谢谢!

下面是我的SQLiteOpenHelper类:

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


public class Database extends SQLiteOpenHelper
{

    public Context DBcontext = null;
    //DatabaseContract version
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "Sensors";



    public static final String SENSOR_DATA_TABLE_NAME ="SensorData";
    public static final String SENSOR_DATA_COLUMN_ID = "SensorDataID";
    public static final String NODE_COLUMN_NAME = "Nodes";
    public static final String TEMP_COLUMN_NAME = "TemperatureData";
    public static final String MOTION_COLUMN_NAME = "MotionData";
    public static final String GAS_COLUMN_NAME = "GasData";
    public static final String LIGHT_COLUMN_NAME = "LightData";



    //Constructor for the Database activity
    public DatabaseContract( Context context , String name, SQLiteDatabase.CursorFactory factory, int version) {
        super( context, name, factory, version);
    }



    @Override
    public void onCreate(SQLiteDatabase db) {


        db.execSQL("CREATE TABLE "+SENSOR_DATA_TABLE_NAME+" ("+SENSOR_DATA_COLUMN_ID+" INTEGER PRIMARY KEY, "+NODE_COLUMN_NAME+ " STRING, "+TEMP_COLUMN_NAME+" STRING,     "+MOTION_COLUMN_NAME+" STRING, "+GAS_COLUMN_NAME+" STRING, "+ LIGHT_COLUMN_NAME+" STRING)");


    }


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    {

        db.execSQL("DROP TABLE IF EXISTS " + SENSOR_DATA_TABLE_NAME);
        onCreate(db);
    }


    public boolean checkExist()
    {

        SQLiteDatabase db = getReadableDatabase();

        String query = "SELECT * FROM "+ SENSOR_DATA_TABLE_NAME;

        Cursor res = db.rawQuery(query, null);


        if(res.getCount() > 0){
            res.close();
            return true;
        }else {
            res.close();
            return false;
        }


    }



    public void updateSensorData(String node_number, String temp_data, String motion_data, String light_data, String gas_data)
    {

        SQLiteDatabase db = getWritableDatabase();
        String query = "SELECT * FROM " + SENSOR_DATA_TABLE_NAME + " WHERE " + NODE_COLUMN_NAME + " ='" + node_number + "'";
        Cursor res = db.rawQuery(query, null);



       if (res.getCount() == 0){
           res.close();
           ContentValues content = new ContentValues();
           content.put(NODE_COLUMN_NAME, node_number);
           content.put(TEMP_COLUMN_NAME, temp_data);
           content.put(MOTION_COLUMN_NAME, motion_data);
           content.put(GAS_COLUMN_NAME, gas_data);
           content.put(LIGHT_COLUMN_NAME, light_data);
           db.insert(SENSOR_DATA_TABLE_NAME, null, content);


       }else{

           /**try to get ID from cursor, not working so hardcoded 1 for now to test**/
           //String ID = Long.toString(res.getLong(res.getColumnIndex(SENSOR_DATA_COLUMN_ID)));
           ContentValues contentValues = new ContentValues();
           contentValues.put(NODE_COLUMN_NAME, node_number);
           contentValues.put(TEMP_COLUMN_NAME, temp_data);
           contentValues.put(MOTION_COLUMN_NAME, motion_data);
           contentValues.put(GAS_COLUMN_NAME, gas_data);
           contentValues.put(LIGHT_COLUMN_NAME, light_data);

           //hardcoded ID = 1 just for testing
           db.update(SENSOR_DATA_TABLE_NAME, contentValues, SENSOR_DATA_COLUMN_ID + " = ? ", new String[] { "1" } );


       }


    }


}

下面是与上面的类交互以在数据库中插入/更新数据的片段。我使用了Google BluetoothChat应用程序并将其修改为符合我的预期目的。此片段与MESSAGE_READ的处理程序中的Database类进行交互。我解析发送给我的数据,然后将其作为参数传递给数据库函数updateSensorData,在那里它负责插入然后更新数据。

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;


public class Bluetooth extends Fragment
{
    private static final String TAG = "Bluetooth";

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE_INSECURE = 1;
    private static final int REQUEST_ENABLE_BT = 2;

    // Layout Views
    private Button scan_button;
    private Button move;
    private DatabaseContract dbHelper;

    /**
     * Name of the connected device
     */
    private String mConnectedDeviceName = null;


    /**
     * Local Bluetooth adapter
     */
    private BluetoothAdapter BAdapter = null;

    /**
     * Member object for the chat services
     */
    private BluetoothChatService mChatService = null;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setHasOptionsMenu(true);
        // Get local Bluetooth adapter
        BAdapter = BluetoothAdapter.getDefaultAdapter();


        if (BAdapter == null)
        {
            FragmentActivity activity = getActivity();
            new AlertDialog.Builder(activity)
                    .setTitle("Error: Not compatible")
                    .setMessage("Your phone does not support Bluetooth")
                    .setPositiveButton("Exit", new DialogInterface.OnClickListener()
                    {
                        public void onClick(DialogInterface dialog, int which)
                        {
                            System.exit(0);
                        }
                    })
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .show();

        }
    }



    @Override
    public void onStart()
    {
        super.onStart();

        if (!BAdapter.isEnabled())
        {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
            // Otherwise, setup the chat session
        }
        else if (mChatService == null)
        {
            setupChat();
        }
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();

        if (mChatService != null)
        {
            mChatService.stop();
        }
    }



    @Override
    public void onResume()
    {
        super.onResume();

        // Performing this check in onResume() covers the case in which BT was
        // not enabled during onStart(), so we were paused to enable it...
        // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
        if (mChatService != null)
        {
            // Only if the state is STATE_NONE, do we know that we haven't started already
            if (mChatService.getState() == BluetoothChatService.STATE_NONE)
            {
                // Start the Bluetooth chat services
                mChatService.start();
            }
        }
        scan_button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {

                Intent serverIntent = new Intent(getActivity(), DeviceList.class);
                startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);

            }
        });
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState)
    {
        View v = inflater.inflate(R.layout.bluetooth, container, false);

        Button move = (Button)v.findViewById(R.id.move);
        move.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), Network.class);
                startActivity(intent);
            }
        });
        return v;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
    {
        scan_button = (Button) view.findViewById(R.id.scan_button);
        move = (Button) view.findViewById(R.id.move);
    }

    /**
     * Set up the UI and background operations for chat.
     */
    private void setupChat()
    {

        scan_button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {

                Intent serverIntent = new Intent(getActivity(), DeviceList.class);
                startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);

            }
        });


        // Initialize the BluetoothChatService to perform bluetooth connections
        mChatService = new BluetoothChatService(getActivity(), mHandler);


    }



    private final Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            FragmentActivity activity = getActivity();
            switch (msg.what)
            {
                case Constants.MESSAGE_STATE_CHANGE:
                    switch (msg.arg1)
                    {
                        case BluetoothChatService.STATE_CONNECTED:
                            Toast.makeText(getActivity(), "Connected to "+mConnectedDeviceName+" setting up network. . .", Toast.LENGTH_SHORT).show();
                            final Handler handler = new Handler();
                            handler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    move.setVisibility(View.VISIBLE);
                                    scan_button.setVisibility(View.INVISIBLE);
                                }
                            }, 4000);

                            break;
                        case BluetoothChatService.STATE_CONNECTING:
                            Toast.makeText(getActivity(), "Connecting. . .", Toast.LENGTH_SHORT).show();
                            break;
                        case BluetoothChatService.STATE_LISTEN:

                        case BluetoothChatService.STATE_NONE:

                            scan_button.setVisibility(View.VISIBLE);
                            move.setVisibility(View.INVISIBLE);
                    }
                    break;

                /******************************** where this fragment interacts with SQLiteOpenHelper class for database******************************/


                case Constants.MESSAGE_READ:
                    byte[] readBuf = (byte[]) msg.obj;
                    // construct a string from the valid bytes in the buffer
                    String readMessage = new String(readBuf, 0, msg.arg1);

                    dbHelper = new DatabaseContract(getActivity(), "data transfer for sensors", null, 1);

                    int node = readMessage.indexOf("node");
                    int temp_number = readMessage.indexOf("t");
                    int motion_number = readMessage.indexOf("m");
                    int light_number = readMessage.indexOf("l");
                    int gas_number = readMessage.indexOf("g");

                    String node_number = readMessage.substring(node + 5, node + 6);
                    String temp_data = readMessage.substring(temp_number, motion_number);
                    String motion_data = readMessage.substring(motion_number, light_number);
                    String light_data = readMessage.substring(light_number, gas_number);
                    String gas_data = readMessage.substring(gas_number);

                    dbHelper.updateSensorData(node_number, temp_data, motion_data, light_data, gas_data);


                    break;
                case Constants.MESSAGE_DEVICE_NAME:
                    // save the connected device's name
                    mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);

                    break;
                case Constants.MESSAGE_TOAST:
                    if (null != activity) {
                        Toast.makeText(activity, msg.getData().getString(Constants.TOAST),
                                Toast.LENGTH_SHORT).show();
                    }
                    break;
            }
        }
    };

    //automatically invoked when app starts up
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        switch (requestCode)
        {
            case REQUEST_CONNECT_DEVICE_INSECURE:
                // When DeviceList returns with a device to connect
                if (resultCode == Activity.RESULT_OK)
                {
                    connectDevice(data, false);
                }
                break;
            case REQUEST_ENABLE_BT:
                // When the request to enable Bluetooth returns
                if (resultCode == Activity.RESULT_OK)
                {
                    // Bluetooth is now enabled, so set up a chat session
                    setupChat();
                }
                else
                {
                    FragmentActivity activity = getActivity();
                    new AlertDialog.Builder(activity)
                            .setTitle("Error")
                            .setMessage("Bluetooth is disabled")
                            .setPositiveButton("ENABLE", new DialogInterface.OnClickListener()
                            {
                                public void onClick(DialogInterface dialog, int which)
                                {

                                    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                                    startActivityForResult(enableIntent, 8);
                                    onDestroy();
                                    onResume();
                                }
                            })
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .show();
                }
        }
    }


    private void connectDevice(Intent data, boolean insecure)
    {
        // Get the device MAC address
        String address = data.getExtras()
                .getString(DeviceList.EXTRA_DEVICE_ADDRESS);
        // Get the BluetoothDevice object
        BluetoothDevice device = BAdapter.getRemoteDevice(address);
        // Attempt to connect to the device
        mChatService.connect(device, insecure);
    }


}

以下是需要访问数据库中信息的其中一个类的示例。我使用checkExist()函数测试它并返回false,尽管在片段中我成功插入然后更新传感器数据。这就是我的问题所在,不确定为什么它不会从数据库中提取任何东西

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.TextView;


/**Here is an example of one of the activities that needs to pull readings from the database to display**/

public class NodeData extends AppCompatActivity
{


    private DatabaseContract dbHelper;
    private TextView tempDisplay;
    private TextView motionDisplay;
    private TextView gasDisplay;
    private TextView lightDisplay;
    private ListView dataDisplay;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.nodedata);
        String node_number = getIntent().getExtras().getString("node_number");
        String label = "Node "+node_number+" Data";
        TextView textViewToChange = (TextView) findViewById(R.id.node_data_label);
        textViewToChange.setText(label);


        dbHelper = new DatabaseContract(getApplicationContext(), "data transfer for sensors", null, 1);


        boolean test = dbHelper.checkExist();

        Toast.makeText(getApplicationContext(), "testing: "+test, Toast.LENGTH_SHORT).show();

    }


}

2 个答案:

答案 0 :(得分:0)

扩展活动中的LoaderManager.LoaderCallbacks以从数据库加载数据。

有关详细信息,请阅读: https://developer.android.com/guide/components/loaders.html

答案 1 :(得分:0)

看到这个: http://guides.codepath.com/android/local-databases-with-sqliteopenhelper

  1. 我建议您使用单例模式以避免泄漏并每次重新分配数据库。
  2. 强烈建议使用startTransaction和endTransaction,如上面的链接所述。
  3. 如果它仍然不起作用,我还建议您使用装载机作为@Bruno建议。

    无论您的问题是什么,只是一个小的潜在错误修复 - 在函数Database的{​​{1}}类中,您忘记关闭其他流程中的updateSensorData