更新:我需要覆盖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();
}
}
答案 0 :(得分:0)
扩展活动中的LoaderManager.LoaderCallbacks以从数据库加载数据。
有关详细信息,请阅读: https://developer.android.com/guide/components/loaders.html
答案 1 :(得分:0)
看到这个: http://guides.codepath.com/android/local-databases-with-sqliteopenhelper
如果它仍然不起作用,我还建议您使用装载机作为@Bruno建议。
无论您的问题是什么,只是一个小的潜在错误修复 - 在函数Database
的{{1}}类中,您忘记关闭其他流程中的updateSensorData
。