Using Android Accelerometer and SMS while phone is sleeping - java

I have an app that records the accelerometer data and send a SMS when a treshhold is passed. It works fine when the phone is awake. What do I need to do so this is also do the same when the phone is locked/sleeping:
I have two activites SendSMSActivity.java:
package com.example.sendsms;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.Menu;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.FilterQueryProvider;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class SendSMSActivity extends Activity implements SensorEventListener {
SendSMS mSender = new SendSMS();
private SensorManager senSensorManager;
private Sensor senAccelerometer;
private long lastUpdate;
private float last_x, last_y, last_z;
//Contacts variable
AutoCompleteTextView emailText;
ContentResolver cr;
SimpleCursorAdapter emailAdapter;
protected void onResume() {
super.onResume();
senSensorManager.registerListener(this, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
senSensorManager.unregisterListener(this);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
//To change body of implemented methods use File | Settings | File Templates.
Sensor mySensor = sensorEvent.sensor;
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
long curTime = System.currentTimeMillis();
// only allow one update every 100ms.
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
float speed = Math.abs(x+y+z - last_x - last_y - last_z)/ diffTime * 10000;
TextView threshText = (TextView)findViewById(R.id.thresh);
if (speed > Float.parseFloat(threshText.getText().toString())) {
Toast.makeText(this, "shake detected w/ speed: " + speed, Toast.LENGTH_SHORT).show();
Toast.makeText(this, "shake detected w/ speed: " + speed, Toast.LENGTH_SHORT).show();
TextView resultText = (TextView)findViewById(R.id.xacc);
resultText.setText("shake detected w/ speed: " + speed);
sendit2();
}
last_x = x;
last_y = y;
last_z = z;
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// can be safely ignored for this demo
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get an instance of the SensorManager
senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
senSensorManager.registerListener(this, senAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
//Contacts
cr = getContentResolver();
emailText = (AutoCompleteTextView) findViewById(R.id.mobileNo);
String[] fromCols = {
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.DATA,
};
int[] toViewIds = { R.id.list_name, R.id.list_email };
emailAdapter = new SimpleCursorAdapter(this, R.layout.email_and_name, getNamesAndEmails(null), fromCols, toViewIds);
// Important 1: You have to provide a way of making the chosen choice look presentable.
// emailAdapter.setStringConversionColumn(1); // 1=DISPLAY_NAME, 2=Email
emailAdapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
#Override
public CharSequence convertToString(Cursor cursor) {
return String.format("%s <%s>", cursor.getString(1).trim(), cursor.getString(2).trim());
}
});
// Important 2: You have to provide a query containing the values on demand
emailAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
String partialItemName = null;
if (constraint != null) {
partialItemName = constraint.toString();
}
return getNamesAndEmails(partialItemName);
}
});
emailText.setAdapter(emailAdapter);
}
//Contacts
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
final static String[] PROJECTION = new String[] {
ContactsContract.RawContacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.DATA,
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
};
/** Get the contacts that have email addresses matching "partialName".
* #author Modified from code obtained from
* http://stackoverflow.com/questions/5205999/android-get-a-cursor-only-with-contacts-that-have-an-email-listed-android-2-0
* #return
*/
Cursor getNamesAndEmails(String partialName) {
// Look for partialName either in display name (person name) or in email
final String filter =
ContactsContract.Contacts.DISPLAY_NAME + " LIKE '%" + partialName + "%'" +
" OR " +
ContactsContract.CommonDataKinds.Phone.DATA + " LIKE '%" + partialName + "%'";
// If display name contains "#" (maybe it's null so Contacts provides email here),
// order by email, else order by display name.
final String order = "CASE WHEN "
+ ContactsContract.Contacts.DISPLAY_NAME
+ " NOT LIKE '%#%' THEN 1 ELSE 2 END, "
+ ContactsContract.Contacts.DISPLAY_NAME
+ ", "
+ ContactsContract.CommonDataKinds.Phone.DATA
+ " COLLATE NOCASE";
// Now make a Cursor containing the contacts that now match partialName as per "filter".
return cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, filter, null, order);
}
public void sendit(View v) {
TextView mobileNum = (TextView)findViewById(R.id.mobileNo);
boolean success = mSender.sendSMSMessage(mobileNum.getText().toString(),
// This is standard lorem-ipsum text, do not bother
// trying to wrap it, there's about 500 characters...
"Movement detected."
);
Toast.makeText(this, "Message sent " + (
success ? "successfully" : "unsuccessfully"),
Toast.LENGTH_SHORT).show();
TextView resultText = (TextView)findViewById(R.id.xacc);
resultText.setText("Message Sent");
}
public void sendit2() {
TextView mobileNum = (TextView)findViewById(R.id.mobileNo);
boolean success = mSender.sendSMSMessage(mobileNum.getText().toString(),
// This is standard lorem-ipsum text, do not bother
// trying to wrap it, there's about 500 characters...
"Movement detected."
);
Toast.makeText(this, "Message sent " + (
success ? "successfully" : "unsuccessfully"),
Toast.LENGTH_SHORT).show();
TextView resultText = (TextView)findViewById(R.id.xacc);
resultText.setText("Message Sent");
}
}
and SendSMS.java:
package com.example.sendsms;
import java.util.ArrayList;
import android.telephony.SmsManager;
import android.util.Log;
/** The code for dealing with the SMS manager;
* called from the GUI code.
*/
public class SendSMS {
static String TAG = "SendSMS";
SmsManager mSMSManager = null;
/* The list of message parts our messge
* gets broken up into by SmsManger */
ArrayList<String> mFragmentList = null;
/* Service Center - not used */
String mServiceCentreAddr = null;
SendSMS() {
mSMSManager = SmsManager.getDefault();
}
/* Called from the GUI to send one message to one destination */
public boolean sendSMSMessage(
String aDestinationAddress,
String aMessageText) {
if (mSMSManager == null) {
return (false);
}
mFragmentList = mSMSManager.divideMessage(aMessageText);
int fragmentCount = mFragmentList.size();
if (fragmentCount > 1) {
Log.d(TAG, "Sending " + fragmentCount + " parts");
mSMSManager.sendMultipartTextMessage(aDestinationAddress,
mServiceCentreAddr,
mFragmentList, null, null);
} else {
Log.d(TAG, "Sendine one part");
mSMSManager.sendTextMessage(aDestinationAddress,
mServiceCentreAddr,
aMessageText, null, null);
}
return true;
}
}

Related

Unable to access current frame being processed in the "ML Kit Vision Quickstart Sample App"

I am working on an android project where I have access facial landmarks from the currently processed frame. Then I have to perform some calculation based on the face positions. At last I have to save the current frame being processed.
For this I am using ML Kit Vision Quickstart Sample App. This code is doing most of my work. From this code I am using the LivePreviewActivity.java, FaceDetectorProcessor.java and FaceGraphic.java class. I have performed all the calculations inside the FaceGraphics.java class. But I am NOT able to access the frame that is being processed currently.
LivePreviewActivity.java
/*
* Copyright 2020 Google LLC. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.mlkit.vision.demo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.google.android.gms.common.annotation.KeepName;
import com.google.mlkit.common.model.LocalModel;
import com.google.mlkit.vision.demo.automl.AutoMLImageLabelerProcessor;
import com.google.mlkit.vision.demo.barcodescanner.BarcodeScannerProcessor;
import com.google.mlkit.vision.demo.facedetector.FaceDetectorProcessor;
import com.google.mlkit.vision.demo.labeldetector.LabelDetectorProcessor;
import com.google.mlkit.vision.demo.objectdetector.ObjectDetectorProcessor;
import com.google.mlkit.vision.demo.preference.PreferenceUtils;
import com.google.mlkit.vision.demo.preference.SettingsActivity;
import com.google.mlkit.vision.demo.preference.SettingsActivity.LaunchSource;
import com.google.mlkit.vision.demo.textdetector.TextRecognitionProcessor;
import com.google.mlkit.vision.face.FaceDetectorOptions;
import com.google.mlkit.vision.label.custom.CustomImageLabelerOptions;
import com.google.mlkit.vision.label.defaults.ImageLabelerOptions;
import com.google.mlkit.vision.objects.custom.CustomObjectDetectorOptions;
import com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Live preview demo for ML Kit APIs.
*/
#KeepName
public final class LivePreviewActivity extends AppCompatActivity
implements OnRequestPermissionsResultCallback,
OnItemSelectedListener,
CompoundButton.OnCheckedChangeListener {
private static final String FACE_DETECTION = "Face Detection";
private static final String TAG = "LivePreviewActivity";
private static final int PERMISSION_REQUESTS = 1;
private CameraSource cameraSource = null;
private CameraSourcePreview preview;
private GraphicOverlay graphicOverlay;
private String selectedModel = FACE_DETECTION;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_vision_live_preview);
preview = findViewById(R.id.preview);
if (preview == null) {
Log.d(TAG, "Preview is null");
}
graphicOverlay = findViewById(R.id.graphic_overlay);
if (graphicOverlay == null) {
Log.d(TAG, "graphicOverlay is null");
}
Spinner spinner = findViewById(R.id.spinner);
List<String> options = new ArrayList<>();
options.add(FACE_DETECTION);
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(this, R.layout.spinner_style, options);
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinner.setAdapter(dataAdapter);
spinner.setOnItemSelectedListener(this);
ToggleButton facingSwitch = findViewById(R.id.facing_switch);
facingSwitch.setOnCheckedChangeListener(this);
ImageView settingsButton = findViewById(R.id.settings_button);
settingsButton.setOnClickListener(
v -> {
Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
intent.putExtra(SettingsActivity.EXTRA_LAUNCH_SOURCE,
SettingsActivity.LaunchSource.LIVE_PREVIEW);
startActivity(intent);
});
if (allPermissionsGranted()) {
createCameraSource(selectedModel);
} else {
getRuntimePermissions();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.live_preview_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.settings) {
Intent intent = new Intent(this, SettingsActivity.class);
intent.putExtra(SettingsActivity.EXTRA_LAUNCH_SOURCE, LaunchSource.LIVE_PREVIEW);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public synchronized void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
selectedModel = parent.getItemAtPosition(pos).toString();
Log.d(TAG, "Selected model: " + selectedModel);
preview.stop();
if (allPermissionsGranted()) {
createCameraSource(selectedModel);
startCameraSource();
} else {
getRuntimePermissions();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.d(TAG, "Set facing");
if (cameraSource != null) {
if (isChecked) {
cameraSource.setFacing(CameraSource.CAMERA_FACING_FRONT);
} else {
cameraSource.setFacing(CameraSource.CAMERA_FACING_BACK);
}
}
preview.stop();
startCameraSource();
}
private void createCameraSource(String model) {
// If there's no existing cameraSource, create one.
if (cameraSource == null) {
cameraSource = new CameraSource(this, graphicOverlay);
}
try {
Log.i(TAG, "Using Face Detector Processor");
FaceDetectorOptions faceDetectorOptions = new FaceDetectorOptions.Builder()
.setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
.build();
// PreferenceUtils.getFaceDetectorOptionsForLivePreview(this);
cameraSource.setMachineLearningFrameProcessor(
new FaceDetectorProcessor(this, faceDetectorOptions));
} catch (Exception e) {
Log.e(TAG, "Can not create image processor: " + model, e);
Toast.makeText(
getApplicationContext(),
"Can not create image processor: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
}
/**
* Starts or restarts the camera source, if it exists. If the camera source doesn't exist yet
* (e.g., because onResume was called before the camera source was created), this will be called
* again when the camera source is created.
*/
private void startCameraSource() {
if (cameraSource != null) {
try {
if (preview == null) {
Log.d(TAG, "resume: Preview is null");
}
if (graphicOverlay == null) {
Log.d(TAG, "resume: graphOverlay is null");
}
preview.start(cameraSource, graphicOverlay);
} catch (IOException e) {
Log.e(TAG, "Unable to start camera source.", e);
cameraSource.release();
cameraSource = null;
}
}
}
#Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
createCameraSource(selectedModel);
startCameraSource();
}
/**
* Stops the camera.
*/
#Override
protected void onPause() {
super.onPause();
preview.stop();
}
#Override
public void onDestroy() {
super.onDestroy();
if (cameraSource != null) {
cameraSource.release();
}
}
private String[] getRequiredPermissions() {
try {
PackageInfo info =
this.getPackageManager()
.getPackageInfo(this.getPackageName(), PackageManager.GET_PERMISSIONS);
String[] ps = info.requestedPermissions;
if (ps != null && ps.length > 0) {
return ps;
} else {
return new String[0];
}
} catch (Exception e) {
return new String[0];
}
}
private boolean allPermissionsGranted() {
for (String permission : getRequiredPermissions()) {
if (!isPermissionGranted(this, permission)) {
return false;
}
}
return true;
}
private void getRuntimePermissions() {
List<String> allNeededPermissions = new ArrayList<>();
for (String permission : getRequiredPermissions()) {
if (!isPermissionGranted(this, permission)) {
allNeededPermissions.add(permission);
}
}
if (!allNeededPermissions.isEmpty()) {
ActivityCompat.requestPermissions(
this, allNeededPermissions.toArray(new String[0]), PERMISSION_REQUESTS);
}
}
#Override
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
Log.i(TAG, "Permission granted!");
if (allPermissionsGranted()) {
createCameraSource(selectedModel);
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private static boolean isPermissionGranted(Context context, String permission) {
if (ContextCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Permission granted: " + permission);
return true;
}
Log.i(TAG, "Permission NOT granted: " + permission);
return false;
}
}
FaceDetectorProcessor.java
/*
* Copyright 2020 Google LLC. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.mlkit.vision.demo.facedetector;
import android.content.Context;
import android.graphics.PointF;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.Task;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.demo.GraphicOverlay;
import com.google.mlkit.vision.demo.VisionProcessorBase;
import com.google.mlkit.vision.face.Face;
import com.google.mlkit.vision.face.FaceDetection;
import com.google.mlkit.vision.face.FaceDetector;
import com.google.mlkit.vision.face.FaceDetectorOptions;
import com.google.mlkit.vision.face.FaceLandmark;
import java.util.List;
import java.util.Locale;
/**
* Face Detector Demo.
*/
public class FaceDetectorProcessor extends VisionProcessorBase<List<Face>> {
private static final String TAG = "FaceDetectorProcessor";
private final FaceDetector detector;
public FaceDetectorProcessor(Context context) {
this(
context,
new FaceDetectorOptions.Builder()
.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
.enableTracking()
.build());
}
public FaceDetectorProcessor(Context context, FaceDetectorOptions options) {
super(context);
Log.v(MANUAL_TESTING_LOG, "Face detector options: " + options);
detector = FaceDetection.getClient(options);
}
#Override
public void stop() {
super.stop();
detector.close();
}
#Override
protected Task<List<Face>> detectInImage(InputImage image) {
return detector.process(image);
}
#Override
protected void onSuccess(#NonNull List<Face> faces, #NonNull GraphicOverlay graphicOverlay) {
for (Face face : faces) {
graphicOverlay.add(new FaceGraphic(graphicOverlay, face));
logExtrasForTesting(face);
}
}
private static void logExtrasForTesting(Face face) {
if (face != null) {
Log.v(MANUAL_TESTING_LOG, "face bounding box: " + face.getBoundingBox().flattenToString());
Log.v(MANUAL_TESTING_LOG, "face Euler Angle X: " + face.getHeadEulerAngleX());
Log.v(MANUAL_TESTING_LOG, "face Euler Angle Y: " + face.getHeadEulerAngleY());
Log.v(MANUAL_TESTING_LOG, "face Euler Angle Z: " + face.getHeadEulerAngleZ());
// All landmarks
int[] landMarkTypes =
new int[]{
FaceLandmark.MOUTH_BOTTOM,
FaceLandmark.MOUTH_RIGHT,
FaceLandmark.MOUTH_LEFT,
FaceLandmark.RIGHT_EYE,
FaceLandmark.LEFT_EYE,
FaceLandmark.RIGHT_EAR,
FaceLandmark.LEFT_EAR,
FaceLandmark.RIGHT_CHEEK,
FaceLandmark.LEFT_CHEEK,
FaceLandmark.NOSE_BASE
};
String[] landMarkTypesStrings =
new String[]{
"MOUTH_BOTTOM",
"MOUTH_RIGHT",
"MOUTH_LEFT",
"RIGHT_EYE",
"LEFT_EYE",
"RIGHT_EAR",
"LEFT_EAR",
"RIGHT_CHEEK",
"LEFT_CHEEK",
"NOSE_BASE"
};
for (int i = 0; i < landMarkTypes.length; i++) {
FaceLandmark landmark = face.getLandmark(landMarkTypes[i]);
if (landmark == null) {
Log.v(
MANUAL_TESTING_LOG,
"No landmark of type: " + landMarkTypesStrings[i] + " has been detected");
} else {
PointF landmarkPosition = landmark.getPosition();
String landmarkPositionStr =
String.format(Locale.US, "x: %f , y: %f", landmarkPosition.x, landmarkPosition.y);
Log.v(
MANUAL_TESTING_LOG,
"Position for face landmark: "
+ landMarkTypesStrings[i]
+ " is :"
+ landmarkPositionStr);
}
}
Log.v(
MANUAL_TESTING_LOG,
"face left eye open probability: " + face.getLeftEyeOpenProbability());
Log.v(
MANUAL_TESTING_LOG,
"face right eye open probability: " + face.getRightEyeOpenProbability());
Log.v(MANUAL_TESTING_LOG, "face smiling probability: " + face.getSmilingProbability());
Log.v(MANUAL_TESTING_LOG, "face tracking id: " + face.getTrackingId());
}
}
#Override
protected void onFailure(#NonNull Exception e) {
Log.e(TAG, "Face detection failed " + e);
}
}
FaceGraphics.java
/*
* Copyright 2020 Google LLC. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.mlkit.vision.demo.facedetector;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.Log;
import com.google.mlkit.vision.demo.GraphicOverlay;
import com.google.mlkit.vision.demo.GraphicOverlay.Graphic;
import com.google.mlkit.vision.face.Face;
import com.google.mlkit.vision.face.FaceContour;
import com.google.mlkit.vision.face.FaceLandmark;
import com.google.mlkit.vision.face.FaceLandmark.LandmarkType;
import java.util.Locale;
/**
* Graphic instance for rendering face position, contour, and landmarks within the associated
* graphic overlay view.
*/
public class FaceGraphic extends Graphic {
private static final float FACE_POSITION_RADIUS = 4.0f;
private static final float ID_TEXT_SIZE = 30.0f;
private static final float ID_Y_OFFSET = 40.0f;
private static final float ID_X_OFFSET = -40.0f;
private static final float BOX_STROKE_WIDTH = 5.0f;
private static final int NUM_COLORS = 10;
private static final int[][] COLORS = new int[][]{
// {Text color, background color}
{Color.BLACK, Color.WHITE},
{Color.WHITE, Color.MAGENTA},
{Color.BLACK, Color.LTGRAY},
{Color.WHITE, Color.RED},
{Color.WHITE, Color.BLUE},
{Color.WHITE, Color.DKGRAY},
{Color.BLACK, Color.CYAN},
{Color.BLACK, Color.YELLOW},
{Color.WHITE, Color.BLACK},
{Color.BLACK, Color.GREEN}
};
private final Paint facePositionPaint;
private final Paint[] idPaints;
private final Paint[] boxPaints;
private final Paint[] labelPaints;
private volatile Face face;
FaceGraphic(GraphicOverlay overlay, Face face) {
super(overlay);
this.face = face;
final int selectedColor = Color.WHITE;
facePositionPaint = new Paint();
facePositionPaint.setColor(selectedColor);
int numColors = COLORS.length;
idPaints = new Paint[numColors];
boxPaints = new Paint[numColors];
labelPaints = new Paint[numColors];
for (int i = 0; i < numColors; i++) {
idPaints[i] = new Paint();
idPaints[i].setColor(COLORS[i][0] /* text color */);
idPaints[i].setTextSize(ID_TEXT_SIZE);
boxPaints[i] = new Paint();
boxPaints[i].setColor(COLORS[i][1] /* background color */);
boxPaints[i].setStyle(Paint.Style.STROKE);
boxPaints[i].setStrokeWidth(BOX_STROKE_WIDTH);
labelPaints[i] = new Paint();
labelPaints[i].setColor(COLORS[i][1] /* background color */);
labelPaints[i].setStyle(Paint.Style.FILL);
}
}
/**
* Draws the face annotations for position on the supplied canvas.
*/
#Override
public void draw(Canvas canvas) {
Face face = this.face;
if (face == null) {
return;
}
// Draws a circle at the position of the detected face, with the face's track id below.
float x0 = translateX(face.getBoundingBox().centerX());
float y0 = translateY(face.getBoundingBox().centerY());
// canvas.drawCircle(x0, y0, FACE_POSITION_RADIUS, facePositionPaint);
// Calculate positions.
float left = x0 - scale(face.getBoundingBox().width() / 2.0f);
float top = y0 - scale(face.getBoundingBox().height() / 2.0f);
float right = x0 + scale(face.getBoundingBox().width() / 2.0f);
float bottom = y0 + scale(face.getBoundingBox().height() / 2.0f);
float lineHeight = ID_TEXT_SIZE + BOX_STROKE_WIDTH;
float yLabelOffset = -lineHeight;
// Decide color based on face ID
int colorID = (face.getTrackingId() == null)
? 0 : Math.abs(face.getTrackingId() % NUM_COLORS);
/**
// Calculate width and height of label box
float textWidth = idPaints[colorID].measureText("ID: " + face.getTrackingId());
if (face.getSmilingProbability() != null) {
yLabelOffset -= lineHeight;
textWidth = Math.max(textWidth, idPaints[colorID].measureText(
String.format(Locale.US, "Happiness: %.2f", face.getSmilingProbability())));
}
if (face.getLeftEyeOpenProbability() != null) {
yLabelOffset -= lineHeight;
textWidth = Math.max(textWidth, idPaints[colorID].measureText(
String.format(Locale.US, "Left eye: %.2f", face.getLeftEyeOpenProbability())));
}
if (face.getRightEyeOpenProbability() != null) {
yLabelOffset -= lineHeight;
textWidth = Math.max(textWidth, idPaints[colorID].measureText(
String.format(Locale.US, "Right eye: %.2f", face.getLeftEyeOpenProbability())));
}
// Draw labels
canvas.drawRect(left - BOX_STROKE_WIDTH,
top + yLabelOffset,
left + textWidth + (2 * BOX_STROKE_WIDTH),
top,
labelPaints[colorID]);
yLabelOffset += ID_TEXT_SIZE;
canvas.drawRect(left, top, right, bottom, boxPaints[colorID]);
canvas.drawText("ID: " + face.getTrackingId(), left, top + yLabelOffset,
idPaints[colorID]);
yLabelOffset += lineHeight;
**/
/**
// Draws all face contours.
for (FaceContour contour : face.getAllContours()) {
for (PointF point : contour.getPoints()) {
canvas.drawCircle(
translateX(point.x), translateY(point.y), FACE_POSITION_RADIUS, facePositionPaint);
}
}
**/
FaceContour contour = face.getContour(FaceContour.NOSE_BRIDGE);
float x1 = 0, y1 = 0;
for (PointF point : contour.getPoints()) {
// canvas.drawCircle(translateX(point.x), translateY(point.y), FACE_POSITION_RADIUS, facePositionPaint);
x1 = translateX(point.x);
y1 = translateY(point.y);
break;
}
/**
// Draws smiling and left/right eye open probabilities.
if (face.getSmilingProbability() != null) {
canvas.drawText(
"Smiling: " + String.format(Locale.US, "%.2f", face.getSmilingProbability()),
left,
top + yLabelOffset,
idPaints[colorID]);
yLabelOffset += lineHeight;
}
**/
/**
FaceLandmark leftEye = face.getLandmark(FaceLandmark.LEFT_EYE);
if (leftEye != null && face.getLeftEyeOpenProbability() != null) {
canvas.drawText(
"Left eye open: " + String.format(Locale.US, "%.2f", face.getLeftEyeOpenProbability()),
translateX(leftEye.getPosition().x) + ID_X_OFFSET,
translateY(leftEye.getPosition().y) + ID_Y_OFFSET,
idPaints[colorID]);
} else if (leftEye != null && face.getLeftEyeOpenProbability() == null) {
canvas.drawText(
"Left eye",
left,
top + yLabelOffset,
idPaints[colorID]);
yLabelOffset += lineHeight;
} else if (leftEye == null && face.getLeftEyeOpenProbability() != null) {
canvas.drawText(
"Left eye open: " + String.format(Locale.US, "%.2f", face.getLeftEyeOpenProbability()),
left,
top + yLabelOffset,
idPaints[colorID]);
yLabelOffset += lineHeight;
}
FaceLandmark rightEye = face.getLandmark(FaceLandmark.RIGHT_EYE);
if (rightEye != null && face.getRightEyeOpenProbability() != null) {
canvas.drawText(
"Right eye open: " + String.format(Locale.US, "%.2f", face.getRightEyeOpenProbability()),
translateX(rightEye.getPosition().x) + ID_X_OFFSET,
translateY(rightEye.getPosition().y) + ID_Y_OFFSET,
idPaints[colorID]);
} else if (rightEye != null && face.getRightEyeOpenProbability() == null) {
canvas.drawText(
"Right eye",
left,
top + yLabelOffset,
idPaints[colorID]);
yLabelOffset += lineHeight;
} else if (rightEye == null && face.getRightEyeOpenProbability() != null) {
canvas.drawText(
"Right eye open: " + String.format(Locale.US, "%.2f", face.getRightEyeOpenProbability()),
left,
top + yLabelOffset,
idPaints[colorID]);
}
**/
/**
// Draw facial landmarks
drawFaceLandmark(canvas, FaceLandmark.LEFT_EYE);
drawFaceLandmark(canvas, FaceLandmark.RIGHT_EYE);
drawFaceLandmark(canvas, FaceLandmark.LEFT_CHEEK);
drawFaceLandmark(canvas, FaceLandmark.RIGHT_CHEEK);
**/
}
private void drawFaceLandmark(Canvas canvas, #LandmarkType int landmarkType) {
FaceLandmark faceLandmark = face.getLandmark(landmarkType);
if (faceLandmark != null) {
canvas.drawCircle(
translateX(faceLandmark.getPosition().x),
translateY(faceLandmark.getPosition().y),
FACE_POSITION_RADIUS,
facePositionPaint);
}
}
}
In the above code I want to access the current frame being processed. Either inside the LivePreviewActivity or FaceGraphics.java.
Please help me.
By Frame , i am assuming you want the bitmap which satisfy your algorithm . Also as you mentioned that you are using LivePreviewActivity that means you are real time face detection.
There is no way to access the bitmap or current frame from FaceDetectorProcessor
Instead what you need to do is to access the original Image inside VisionProcessorBase.java
modify the common process logic like this to pass the current bitmap to FaceDetectorProcessor
// -----------------Common processing logic-------------------------------------------------------
private Task<T> requestDetectInImage(
final InputImage image,
final GraphicOverlay graphicOverlay,
#Nullable final Bitmap originalCameraImage,
boolean shouldShowFps) {
final long startMs = SystemClock.elapsedRealtime();
return detectInImage(image)
.addOnSuccessListener(
executor,
results -> {
long currentLatencyMs = SystemClock.elapsedRealtime() - startMs;
numRuns++;
frameProcessedInOneSecondInterval++;
totalRunMs += currentLatencyMs;
maxRunMs = Math.max(currentLatencyMs, maxRunMs);
minRunMs = Math.min(currentLatencyMs, minRunMs);
// Only log inference info once per second. When frameProcessedInOneSecondInterval is
// equal to 1, it means this is the first frame processed during the current second.
if (frameProcessedInOneSecondInterval == 1) {
Log.d(TAG, "Max latency is: " + maxRunMs);
Log.d(TAG, "Min latency is: " + minRunMs);
Log.d(TAG, "Num of Runs: " + numRuns + ", Avg latency is: " + totalRunMs / numRuns);
MemoryInfo mi = new MemoryInfo();
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 0x100000L;
Log.d(TAG, "Memory available in system: " + availableMegs + " MB");
}
graphicOverlay.clear();
if (originalCameraImage != null) {
graphicOverlay.add(new CameraImageGraphic(graphicOverlay, originalCameraImage));
}
//passing the original bitmap to FaceDetectorProcessor
VisionProcessorBase.this.onSuccess(originalCameraImage,results, graphicOverlay);
graphicOverlay.add(
new InferenceInfoGraphic(
graphicOverlay, currentLatencyMs, shouldShowFps ? framesPerSecond : null));
graphicOverlay.postInvalidate();
})
.addOnFailureListener(
executor,
e -> {
graphicOverlay.clear();
graphicOverlay.postInvalidate();
String error = "Failed to process. Error: " + e.getLocalizedMessage();
Toast.makeText(
graphicOverlay.getContext(),
error + "\nCause: " + e.getCause(),
Toast.LENGTH_SHORT)
.show();
Log.d(TAG, error);
e.printStackTrace();
VisionProcessorBase.this.onFailure(e);
});
}
You also need to change abstract onSuccess FaceDetectorProcessor like this :
protected abstract void onSuccess(Bitmap currentBitmap,#NonNull T results, #NonNull GraphicOverlay graphicOverlay);
After the required changes , you can access the currentBitmap in onSuccess Method inside FaceDetectorProcessor and you can also pass this to FaceGraphic.java from here
#Override
protected void onSuccess(Bitmap currentBitmap, #NonNull List<Face> faces, #NonNull GraphicOverlay graphicOverlay) {
for (Face face : faces) {
graphicOverlay.add(new FaceGraphic(currentBitmap,graphicOverlay, face));
logExtrasForTesting(face);
}
}
Inside FaceGraphic.java access current bitmap from constructor
FaceGraphic(Bitmap currentBitmap,GraphicOverlay overlay, Face face) {
this.currentBitmap = currentBitmap;
}
I hope this will help you out and fulfill your need.

Why do I get a java.lang.IllegalStateException error in cursor even though column rows are correct?

I have a dictionary app which stores a word with the meaning, type (English,Chinese,Japanese etc) and favorite status (whether it's a favorite word). On 1 of my menu items, there's this item called sort. When I click on it, I am expecting the words in my main page to be sorted in ascending order but instead I got this error in ListFragment.java: 'java.lang.IllegalStateException: Couldn't read row 0, col 4 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.'. There's nothing wrong with my database.
MainActivity.java
package mapp.com.sg.pocketdictionary;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import mapp.com.sg.pocketdictionary.db.WordsDataSource;
public class MainActivity extends AppCompatActivity implements ListFragment.OnContactSelectedInterface/*,SearchView.OnQueryTextListener*/ {
protected WordsDataSource myDataSource;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDataSource = new WordsDataSource(this);
this.setTitle("PD");
//The code here decides whether to create the fragment because it can be destroyed by the Android system
//when it reclaims memory
ListFragment savedFragment = (ListFragment) getSupportFragmentManager().findFragmentByTag("WORDS_FRAGMENT");
if (savedFragment == null) {
ListFragment fragment = new ListFragment();
Bundle bundle = new Bundle();
bundle.putBoolean("isFavourite", false);
fragment.setArguments(bundle);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.placeHolder, fragment, "WORDS_FRAGMENT");
fragmentTransaction.commit();
}
}
#Override
protected void onResume() {
//The code here is required because when I save the data and navigate back
//I need my applicationn logic to refresh the fragement content to reflect the changes
//to avoid the list interface listing the old data.
super.onResume();
ListFragment savedFragment = (ListFragment) getSupportFragmentManager().findFragmentByTag("WORDS_FRAGMENT");
if (savedFragment != null) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.detach(savedFragment);
fragmentTransaction.attach(savedFragment);
fragmentTransaction.commit();
}
}
#Override
public void onListContactSelected(int index) {
//When tap on a row display word, this logic here will start collecting the
//id which is tied to the data and navigate the user to another Activity
//and at the same time pass the id over.
// Toast.makeText(this, "PUMPKINNNNNN", Toast.LENGTH_SHORT).show(); for testing if tap detected
Intent intent = new Intent(this, WordsDetailActivity.class);
intent.putExtra("WordId", index);//index variable name may not be suitable here
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater myMenuInflater = getMenuInflater();
myMenuInflater.inflate(R.menu.menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
String itemTitle = item.getTitle().toString();
if (item.getItemId() == R.id.favourite) {
// Toast.makeText(this, "GER" , Toast.LENGTH_SHORT).show();//Go to favorite action choice detected
startActivity(new Intent(this, FavouriteActivity.class));
} else if (item.getItemId() == R.id.Add) {
// Toast.makeText(this, "EEEEYEERR", Toast.LENGTH_SHORT).show();//Go to add word action choice detected
startActivity(new Intent(this, AddWordsActivity.class));
} else if (item.getItemId() == R.id.sort) {
Bundle bundle = new Bundle();
bundle.putBoolean("isSortByAsc", true);
ListFragment savedFragment = (ListFragment) getSupportFragmentManager().findFragmentByTag("WORDS_FRAGMENT");
if (savedFragment != null) {
savedFragment.setArguments(bundle);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.detach(savedFragment);
fragmentTransaction.attach(savedFragment);
fragmentTransaction.commit();
}
}
}
return super.onOptionsItemSelected(item);
}
}
ListFragment.java
package mapp.com.sg.pocketdictionary;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import mapp.com.sg.pocketdictionary.db.WordsDataSource;
public class ListFragment extends Fragment {
protected WordsDataSource mDataSource;
private boolean isFavourite;
private boolean isSortByAsc;
public interface OnContactSelectedInterface {
void onListContactSelected(int index);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
OnContactSelectedInterface listener = (OnContactSelectedInterface) getActivity();
isFavourite = getArguments().getBoolean("isFavourite");
isSortByAsc = getArguments().getBoolean("isSortByAsc");
View view = inflater.inflate(R.layout.fragment_recycler, container,false);
//-------------------
//The rest of the code below is to read all or favorite word data
//and fill up the ArrayList variable.
mDataSource = new WordsDataSource(getContext());
mDataSource.open();
Cursor cursor;
if(isFavourite){
cursor = mDataSource.selectFavouriteWords();
}
else if (isSortByAsc){
cursor = mDataSource.sortWords();
}
else{
cursor = mDataSource.selectAllWords();
}
ArrayList<Words> wordsList = new ArrayList<>();
cursor.moveToFirst();
while(!cursor.isAfterLast()){
boolean tempFav = true;//The database uses 0 and 1 to represent true or false
//Therefore I used this tempFav so that my logic here can store true or false
//during the getString() call
//Error occurs here
if (cursor.getInt(4) != 0) {
tempFav = false;
}
Words tempWords =new Words(cursor.getString(1),cursor.getString(2),cursor.getString(3),tempFav);
tempWords.setId(cursor.getInt(0));
wordsList.add(tempWords);
//Log.d("MY Activity", "onCreateView: "+ tempWords.getId()+" " + tempWords.getWord()+" " +tempWords.getMeaning()+" "+ tempWords.getType()+" "+ cursor.getInt(4));
Log.d("MY Activity", "cursor: "+ cursor.getInt(0)+ " "+cursor.getString(1)+" " + cursor.getString(2)+" "+cursor.getString(3)+" " + cursor.getInt(4));
//Column 0 is id, column 1 is word, column 2 is meaning, column 3 is type, column 4 is favorite status(0 for true and 1 for false)
cursor.moveToNext();
}
mDataSource.close();
//-----------------------
//After the ArrayList variable is filled with data,
//create a listAdapter type object
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
//Creating a ListAdapter object and at the same time pass in a "walkie-talkie" so that it can
//yell out if any related events happening and also the ArrayList of contect information
ListAdapter listAdapter = new ListAdapter(listener, wordsList);
recyclerView.setAdapter(listAdapter);//Start using it
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
return view;
}
}
WordsDataSource.java
package mapp.com.sg.pocketdictionary.db;
//insert update delete
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import mapp.com.sg.pocketdictionary.Words;
public class WordsDataSource {
private SQLiteDatabase mDatabase;
private WordsHelper mWordsHelper;
private Context mContext;
public WordsDataSource(Context context){
mContext = context;
mWordsHelper = new WordsHelper(mContext);
}
//open data base
public void open() throws SQLException {
mDatabase = mWordsHelper.getWritableDatabase();
}
//close
public void close() {
mDatabase.close();
}
//insert
public void insertWords(Words words) {
mDatabase.beginTransaction();
try{
ContentValues values = new ContentValues();
values.put(WordsHelper.COLUMN_WORD, words.getWord());
values.put(WordsHelper.COLUMN_MEANING, words.getMeaning());
values.put(WordsHelper.COLUMN_TYPE, words.getType());
int fav = 0;
if (!words.isFavourite()) {
fav = 1;
}
values.put(WordsHelper.COLUMN_FAVOURITE, fav);
mDatabase.insert(WordsHelper.TABLE_WORDS, null, values);
mDatabase.setTransactionSuccessful();
} finally {
mDatabase.endTransaction();
}
}
//sort
public Cursor sortWords (){
String[] wordname = new String[]{ WordsHelper.COLUMN_WORD };
Cursor cursor= mDatabase.query(WordsHelper.TABLE_WORDS,wordname , null, null, null, null, WordsHelper.COLUMN_WORD+" ASC");
return cursor;
}
//select
public Cursor selectAllWords(){
Cursor cursor = mDatabase.rawQuery("Select * from " + WordsHelper.TABLE_WORDS, null);
return cursor;
}
public Cursor selectOneWord(int Id){
Cursor cursor = mDatabase.rawQuery("Select * from " + WordsHelper.TABLE_WORDS+" where "
+ WordsHelper.COLUMN_ID+" = " + Id, null);
return cursor;
}
public Cursor selectFavouriteWords() {
Cursor cursor = mDatabase.rawQuery("Select * from " + WordsHelper.TABLE_WORDS+" where "
+ WordsHelper.COLUMN_FAVOURITE+" = 0" , null);
return cursor;
}
//update
public boolean updateWords(int id, String word, String meaning,String type, boolean fav){
ContentValues values = new ContentValues();
int success = -1;
values.put(WordsHelper.COLUMN_WORD, word);
values.put(WordsHelper.COLUMN_MEANING, meaning);
values.put(WordsHelper.COLUMN_TYPE, type);
int favDigit = 0;
if(!fav){
favDigit = 1;
}
values.put(WordsHelper.COLUMN_FAVOURITE, favDigit);
success = mDatabase.update(
WordsHelper.TABLE_WORDS,
values,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success != 0) {
return true;
} else {
return false;
}
}
public boolean setFavourite (int id, boolean fav) {
ContentValues values = new ContentValues();
int success = -1;
int favDigit = 0;
if(!fav){
favDigit = 1;
}
values.put(WordsHelper.COLUMN_FAVOURITE, favDigit);
success = mDatabase.update(
WordsHelper.TABLE_WORDS,
values,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success != 0) {
return true;
} else {
return false;
}
}
public boolean updateWords(int id, String word, String meaning,String type){
ContentValues values = new ContentValues();
int success = -1;
if(word != null ){
values.put(WordsHelper.COLUMN_WORD, word);
}
if(meaning != null ){
values.put(WordsHelper.COLUMN_MEANING, meaning);
}
if(type != null ){
values.put(WordsHelper.COLUMN_TYPE, type);
}
success = mDatabase.update(
WordsHelper.TABLE_WORDS,
values,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success != 0) {
return true;
} else {
return false;
}
}
//delete
public boolean deleteWords(int id) {
int success = -1;
success = mDatabase.delete(
WordsHelper.TABLE_WORDS,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success !=0) {
return true;
} else {
return false;
}
}
public boolean deleteWords() {
int success = -1;
success = mDatabase.delete(
WordsHelper.TABLE_WORDS,
null,
null
);
if(success != -1 ) {
return true;
} else {
return false;
}
}
}
WordsHelper.java
package mapp.com.sg.pocketdictionary.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
//Helps make all code in WordsDataSource neater, readable and maintainable.
public class WordsHelper extends SQLiteOpenHelper {
public static final String TABLE_WORDS ="WORDS";
public static final String COLUMN_ID = "_ID";
public static final String COLUMN_WORD = "WORD";
public static final String COLUMN_MEANING = "MEANING";
public static final String COLUMN_TYPE = "TYPE";
public static final String COLUMN_FAVOURITE = "FAVOURITE";
private static final String DB_NAME = "words.db";
private static final int DB_VER = 1;
private static final String DB_CREATE = "CREATE TABLE "+TABLE_WORDS+
" (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT" +
", " + COLUMN_WORD + " TEXT, " +
COLUMN_MEANING + " TEXT,"+
COLUMN_TYPE + " TEXT,"+ COLUMN_FAVOURITE +" INTEGER)";
public WordsHelper(Context context){
super(context, DB_NAME, null, DB_VER);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(DB_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
As you are trying to read the data, you need to get ReadableDatabase but your open always gets WritableDatabaseas in
Main code
mDataSource = new WordsDataSource(getContext());
mDataSource.openforRead(); // <-- will return readable database
Cursor cursor;
if(isFavourite){
cursor = mDataSource.selectFavouriteWords();
}
else if (isSortByAsc){
cursor = mDataSource.sortWords();
}
else{
cursor = mDataSource.selectAllWords();
}
ArrayList<Words> wordsList = new ArrayList<>();
cursor.moveToFirst();
while(!cursor.isAfterLast()){
boolean tempFav = true;//The database uses 0 and 1 to represent true or false
//Therefore I used this tempFav so that my logic here can store true or false
//during the getString() call
//Error occurs here
if (cursor.getInt(cursor.getColumnIndex(WordsHelper.COLUMN_FAVOURITE)) != 0) {
tempFav = false;
}
Words tempWords =new Words(cursor.getString(1),cursor.getString(2),cursor.getString(3),tempFav);
tempWords.setId(cursor.getInt(0));
wordsList.add(tempWords);
//Log.d("MY Activity", "onCreateView: "+ tempWords.getId()+" " + tempWords.getWord()+" " +tempWords.getMeaning()+" "+ tempWords.getType()+" "+ cursor.getInt(4));
Log.d("MY Activity", "cursor: "+ cursor.getInt(0)+ " "+cursor.getString(1)+" " + cursor.getString(2)+" "+cursor.getString(3)+" " + cursor.getInt(4));
//Column 0 is id, column 1 is word, column 2 is meaning, column 3 is type, column 4 is favorite status(0 for true and 1 for false)
cursor.moveToNext();
}
Add below method to WordsDataSource
public void openForRead() throws SQLException {
mDatabase = mWordsHelper.getReadableDatabase();
}
If you trying to access
int value=cursor.getInt(4)
and it have null value or out of rang of integer it will throw exception.
for such case try below code
if ( !cursor.isNull( columnIndex ) )
{
value = cursor.getInt( columnIndex );
}
else
{
value=0; //default value
}
For debugging purpose first check the value of cursor using below code
Log.d("CursorObject", DatabaseUtils.dumpCursorToString(cursor))

How to insert new data into SQLite

I'm a newbie here.
I need to insert new data (Lat,Lng) into a SQLite database, so I can show all the markers from my table.
Here is my code, MySQLiteHelper.java.
Is it correct?
Please help me
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class MySQLiteHelper extends SQLiteOpenHelper{
public static final String TABLE_LOCATIONS = "locations";
public static final String NAMA = "id_title";
public static final String ID_COL = "loc_id";
public static final String TITLE = "loc_title";
public static final String SNIPPET = "loc_snippet";
public static final String POSITION = "loc_position";
private static final int DB_VERSION = 1;
private static final String DB_NAME = "parkir.db";
private static final String DATABASE_CREATE = "create table "
+ TABLE_LOCATIONS + "(" + ID_COL
+ " integer primary key autoincrement, "
+ " text, "+ TITLE
+ " text, " + SNIPPET
+ " text, " + POSITION
+ " text);";
public MySQLiteHelper(Context context){
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
SQLiteDatabase dba = this.getWritableDatabase();
ContentValues v=new ContentValues();
v.put(MySQLiteHelper.POSITION, "-6.368590, 106.832702");
v.put(MySQLiteHelper.TITLE, "Parkiran Kampus D");
v.put(MySQLiteHelper.SNIPPET, "Kampus Gunadarma yang terletak di Margonda");
dba.insert(MySQLiteHelper.TABLE_LOCATIONS, null,v);
v.put(MySQLiteHelper.POSITION, "-6.353212, 106.841462");
v.put(MySQLiteHelper.TITLE, "Parkiran Kampus E");
v.put(MySQLiteHelper.SNIPPET, "Kampus Gunadarma yang terletak di Kelapa Dua");
dba.insert(MySQLiteHelper.TABLE_LOCATIONS, null,v);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(MySQLiteHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS" + TABLE_LOCATIONS);
onCreate(db);
}
}
This is MyMarker.java code
import com.google.android.gms.maps.model.LatLng;
public class MyMarker {
private long id;
private String title;
private String snippet;
private String position;
private LatLng poLatLng;
public MyMarker() {
}
public MyMarker(long id, String title, String snippet, LatLng poLatLng) {
this.id = id;
this.title = title;
this.snippet = snippet;
this.poLatLng = poLatLng;
this.position = String.valueOf(poLatLng.latitude) + " " + String.valueOf(poLatLng.longitude);
}
public MyMarker(String title, String snippet, LatLng poLatLng){
this.title = title;
this.snippet = snippet;
this.poLatLng = poLatLng;
this.position = String.valueOf(poLatLng.latitude) + " " + String.valueOf(poLatLng.longitude);
}
/**
* #return the id
*/
public long getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* #return the title
*/
public String getTitle() {
return title;
}
/**
* #param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* #return the snippet
*/
public String getSnippet() {
return snippet;
}
/**
* #param snippet the snippet to set
*/
public void setSnippet(String snippet) {
this.snippet = snippet;
}
/**
* #return the position
*/
public String getPosition() {
return position;
}
/**
* #param position the position to set
*/
public void setPosition(LatLng poLatLng) {
this.poLatLng = poLatLng;
this.position = String.valueOf(poLatLng.latitude) + " " + String.valueOf(poLatLng.longitude);
}
/**
* #param position needs to be Latitude</space/>Longitude
*/
public void setPosition(String position) {
this.position = position;
String[] pos = position.split(" ");
this.poLatLng = new LatLng(Double.valueOf(pos[0]), Double.valueOf(pos[1]));
}
public LatLng getLatLng (){
return poLatLng;
}
}
This is my Dataparkir.java code
import android.content.ContentValues;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;
import android.database.Cursor;
import android.util.Log;
public class Dataparkir {
private SQLiteDatabase db;
private MySQLiteHelper dbhelper;
// String id, String title, String snippet, String position
private String[] allColumns = {
MySQLiteHelper.TITLE,
MySQLiteHelper.SNIPPET,
MySQLiteHelper.POSITION };
public Dataparkir(Context context){
dbhelper = new MySQLiteHelper(context);
}
public void open() throws SQLException{
db = dbhelper.getWritableDatabase();
}
public void close(){
dbhelper.close();
}
public void addMarker(MyMarker m){
ContentValues v = new ContentValues();
v.put(MySQLiteHelper.TITLE, m.getTitle());
v.put(MySQLiteHelper.SNIPPET, m.getSnippet());
v.put(MySQLiteHelper.POSITION, m.getPosition());
long insertId = db.insert(MySQLiteHelper.TABLE_LOCATIONS, null,
v);
Cursor cursor = db.query(MySQLiteHelper.TABLE_LOCATIONS,
allColumns, MySQLiteHelper.ID_COL + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
MyMarker mm = cursorToMarker(cursor);
cursor.close();
}
public List<MyMarker> getMyMarkers(){
List<MyMarker> markers = new ArrayList<MyMarker>();
Cursor cursor = db.query(MySQLiteHelper.TABLE_LOCATIONS,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
MyMarker mm = cursorToMarker(cursor);
markers.add(mm);
cursor.moveToNext();
}
cursor.close();
return markers;
}
private MyMarker cursorToMarker(Cursor cursor) {
MyMarker mm = new MyMarker();
mm.setTitle(cursor.getString(0));
mm.setSnippet(cursor.getString(1));
mm.setPosition(cursor.getString(2));
return mm;
}
}
And this is my MainActivity.java
import java.util.List;
import android.content.Context;
import android.content.IntentSender;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.LatLng;
public class MainActivity extends FragmentActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener,
com.google.android.gms.location.LocationListener {
public static final String TAG = MainActivity.class.getSimpleName();
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private GoogleMap googleMap;
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private LocationManager locationManager;
private Criteria criteria;
private Location location;
private SQLiteDatabase db;
private Context context = this;
private Dataparkir data = new Dataparkir(context);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpMapIfNeeded();
setUpMap();
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// Creating a criteria object to retrieve provider
criteria = new Criteria();
// Getting the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
// Getting Current Location
Location location = locationManager.getLastKnownLocation(provider);
if(location!= null){
onLocationChanged(location);
}
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
// Showing / hiding your current location
googleMap.setMyLocationEnabled(true);
// Enable / Disable zooming controls
googleMap.getUiSettings().setZoomControlsEnabled(true);
// Enable / Disable Compass icon
googleMap.getUiSettings().setCompassEnabled(true);
// Enable / Disable Rotate gesture
googleMap.getUiSettings().setRotateGesturesEnabled(true);
// Enable / Disable zooming functionality
googleMap.getUiSettings().setZoomGesturesEnabled(true);
// Enable / Disable Toolbar
googleMap.getUiSettings().setMapToolbarEnabled(false);
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
googleApiClient.connect();
}
#Override
protected void onPause() {
super.onPause();
if (googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, (com.google.android.gms.location.LocationListener) this);
googleApiClient.disconnect();
}
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (googleMap == null) {
// Try to obtain the map from the SupportMapFragment.
googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
// Check if we were successful in obtaining the map.
if (googleMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
try {
data.open();
} catch (SQLException e) {
}
List<MyMarker> markers = data.getMyMarkers();
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.marker);
for (int i = 0; i < markers.size(); i++) {
googleMap.addMarker(new MarkerOptions()
.title(markers.get(i).getTitle())
.snippet(markers.get(i).getSnippet())
.position(markers.get(i).getLatLng())
.icon(icon));
}
data.close();
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
LatLng latLng = new LatLng(currentLatitude, currentLongitude);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
googleMap.animateCamera(CameraUpdateFactory.zoomIn());
googleMap.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng) // Sets the center of the map to Mountain View
.zoom(15) // Sets the zoom
.build(); // Creates a CameraPosition from the builder
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
#Override
public void onConnected(Bundle bundle) {
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, (com.google.android.gms.location.LocationListener) this);
}
else {
handleNewLocation(location);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
// Thrown if Google Play services canceled the original
// PendingIntent
}
catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
}
else {
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onDestroy() {
super.onDestroy();
db.close();
}
}
You miss a column name in the creation of your table:
private static final String DATABASE_CREATE = "create table "
+ TABLE_LOCATIONS + "(" + ID_COL
+ " integer primary key autoincrement, " // + COLUMN_NAME
+ " text, "+ TITLE
+ " text, " + SNIPPET
+ " text, " + POSITION
+ " text);";
I marked where you miss a column name.
Please note that your way of writing that code is confusing.
It would be more readable like this:
private static final String DATABASE_CREATE =
"CREATE TABLE " + TABLE_LOCATIONS + " (" +
ID_COL + " integer primary key autoincrement, " +
COLUMN_NAME + " text, " + // The missing column name
TITLE + " text, " +
SNIPPET + " text, " +
POSITION + " text)";

Android App with SQLite runs in ICS but not Jelly Bean - IllegalStateException

I've developed an app for Android which stores car filling information in an SQLite database. Everything seems to work fine on my 4.0.3 phone and my 4.0.3 AVD, but I would like it to also work in Jelly Bean and newer versions. The app really doesn't do anything very complicated. When I fire the app up in the emulated Jelly Bean device I get a FATAL EXCEPTION error:
09-05 01:45:40.311: W/dalvikvm(1062): threadid=1: thread exiting with uncaught exception >(group=0x414c4700)
09-05 01:45:40.331: E/AndroidRuntime(1062): FATAL EXCEPTION: main
09-05 01:45:40.331: E/AndroidRuntime(1062): java.lang.RuntimeException: Unable to start >activity ComponentInfo{ard.util.fueltracker/ard.util.fueltracker.TitleScreenActivity}: >java.lang.IllegalStateException: attempt to re-open an already-closed object: >SQLiteDatabase: /data/data/ard.util.fueltracker/databases/vehicleDatabase
09-05 01:45:40.331: E/AndroidRuntime(1062): at >android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
In my initial searches in Google I thought I had Instance issues somehow, so I followed Approach #1 here (http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html), but this doesn't seem to make a difference. Still works in ICS with the changes too.
Here's the code from my TitleScreenActivity:
package ard.util.fueltracker;
import java.util.List;
import ard.util.fueltracker.util.SystemUiHider;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.content.Intent;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*
* #see SystemUiHider
*/
#SuppressLint("NewApi")
public class TitleScreenActivity extends Activity implements OnItemSelectedListener {
/**
* Whether or not the system UI should be auto-hidden after
* {#link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = false;
/**
* If {#link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* If set, will toggle the system UI visibility upon interaction. Otherwise,
* will show the system UI visibility upon interaction.
*/
private static final boolean TOGGLE_ON_CLICK = false;
/**
* The flags to pass to {#link SystemUiHider#getInstance}.
*/
//private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
private static final int HIDER_FLAGS = 0;
/**
* The instance of the {#link SystemUiHider} for this activity.
*/
private SystemUiHider mSystemUiHider;
// Spinner element
Spinner spinner;
// Buttons
Button btnAdd;
Button btnLogo;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR); //new
getActionBar().hide(); //new
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_title_screen);
// Spinner element
spinner = (Spinner) findViewById(R.id.titleSelectionSpinner);
// buttons
btnAdd = (Button) findViewById(R.id.button_go);
btnLogo = (Button) findViewById(R.id.button_ard_logo);
// Spinner click listener
spinner.setOnItemSelectedListener(this);
// Check for Add New Vehicle entry to create menu option in drop down list
checkAddNewVehicle();
// Loading spinner data from database
loadSpinnerData();
//"Go" button actions
btnAdd.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
//Starting a new Intent
Intent screenAddVehicle = new Intent(getApplicationContext(), AddVehicleActivity.class);
Intent screenRecordViewing = new Intent(getApplicationContext(), RecordViewing.class);
String SpinnerChoice = spinner.getSelectedItem().toString();
//Sending data to another Activity
//store value of vehicle label for Record Viewing screen
screenRecordViewing.putExtra("vehicleLabel", SpinnerChoice);
//interpret Spinner choice as Menu items
//"Add New Vehicle" always at Position 0
if (SpinnerChoice == spinner.getItemAtPosition(0).toString()) {
startActivity(screenAddVehicle);
} else {
//display value of selection if not "Add New Vehicle"
//Toast.makeText(spinner.getContext(), "Selection:" + SpinnerChoice, Toast.LENGTH_LONG).show();
//go to Record Viewing screen
startActivity(screenRecordViewing);
}
}
});
//"Logo" button - display program copyright
btnLogo.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(), "FuelTracker is Copyright 2013 by Authentic Ruby Designs", Toast.LENGTH_LONG).show();
}
});
final View controlsView = findViewById(R.id.fullscreen_content_controls);
final View contentView = findViewById(R.id.fullscreen_content);
// Set up an instance of SystemUiHider to control the system UI for
// this activity.
mSystemUiHider = SystemUiHider.getInstance(this, contentView,
HIDER_FLAGS);
mSystemUiHider.setup();
mSystemUiHider
.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
// Cached values.
int mControlsHeight;
int mShortAnimTime;
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void onVisibilityChange(boolean visible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
// If the ViewPropertyAnimator API is available
// (Honeycomb MR2 and later), use it to animate the
// in-layout UI controls at the bottom of the
// screen.
if (mControlsHeight == 0) {
mControlsHeight = controlsView.getHeight();
}
if (mShortAnimTime == 0) {
mShortAnimTime = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}
controlsView
.animate()
.translationY(visible ? 0 : mControlsHeight)
.setDuration(mShortAnimTime);
} else {
// If the ViewPropertyAnimator APIs aren't
// available, simply show or hide the in-layout UI
// controls.
controlsView.setVisibility(visible ? View.VISIBLE
: View.GONE);
}
if (visible && AUTO_HIDE) {
// Schedule a hide().
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
}
});
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.button_go).setOnTouchListener(
mDelayHideTouchListener);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
//delayedHide(100);
}
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
Handler mHideHandler = new Handler();
Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
mSystemUiHider.hide();
}
};
/**
* Schedules a call to hide() in [delay] milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
/**
* Function to check that Add New Vehicle is the first label in the DB table
*/
private void checkAddNewVehicle() {
// database handler
//DatabaseHandler db = new DatabaseHandler(getApplicationContext());
DatabaseHandler db = DatabaseHandler.getInstance(getApplicationContext());
// table data
List<String> labels = db.getAllLabels();
//Check for "Add New Vehicle" entry at first row of table
if (labels.isEmpty() ) {
db.insertLabel("Add New Vehicle");
}
}
/**
* Function to load the spinner data from SQLite database
* */
private void loadSpinnerData() {
// database handler
//DatabaseHandler db = new DatabaseHandler(getApplicationContext());
DatabaseHandler db = DatabaseHandler.getInstance(getApplicationContext());
// Spinner Drop down elements
List<String> labels = db.getAllLabels();
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, labels);
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinner.setAdapter(dataAdapter);
}
}
And here's my DatabaseHandler class:
package ard.util.fueltracker;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.TableLayout;
public class DatabaseHandler extends SQLiteOpenHelper {
//create static instance
private static DatabaseHandler mInstance = null;
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "vehicleDatabase";
// Labels table name
private static final String TABLE_LABELS = "labels";
// Fuel Data table name
private static final String TABLE_FUELDATA = "fuel_data";
// Labels Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
// Fuel Data Tables Columns names
private static final String KEY_ENTRY = "entry_id";
private static final String FIELD_VEHICLEID = "vehicle_id";
private static final String FIELD_DATE = "date";
private static final String FIELD_FTYPE = "fuel_type";
private static final String FIELD_BRAND = "brand";
private static final String FIELD_PRICE = "price";
private static final String FIELD_KMS = "kms";
private static final String FIELD_LITRES = "litres";
private static final String FIELD_LPER = "l_per";
private static final String FIELD_MPG = "mpg";
// Fuel Data Columns for display - query shorthand
private static final String[] fuelDataDisplayCols = { FIELD_DATE, FIELD_FTYPE, FIELD_BRAND, FIELD_PRICE,
FIELD_KMS, FIELD_LITRES, FIELD_LPER, FIELD_MPG };
public static DatabaseHandler getInstance(Context ctx) {
//Use the application context to avoid leaking Activity's context
if (mInstance == null) {
mInstance = new DatabaseHandler(ctx.getApplicationContext());
}
return mInstance;
}
private DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
// Category table create query
String CREATE_CATEGORIES_TABLE = "CREATE TABLE " + TABLE_LABELS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT)";
db.execSQL(CREATE_CATEGORIES_TABLE);
// Fuel Data table create query
String CREATE_FUELDATA_TABLE = "CREATE TABLE " + TABLE_FUELDATA + "("
+ KEY_ENTRY + " INTEGER PRIMARY KEY," + FIELD_VEHICLEID + " INTEGER,"
+ FIELD_DATE + " TEXT," + FIELD_FTYPE + " TEXT," + FIELD_BRAND +
" TEXT," + FIELD_PRICE + " REAL," + FIELD_KMS + " REAL,"
+ FIELD_LITRES + " REAL," + FIELD_LPER + " REAL," + FIELD_MPG +
" REAL)";
db.execSQL(CREATE_FUELDATA_TABLE);
db.close();
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_LABELS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FUELDATA);
// Create tables again
onCreate(db);
}
/**
* Inserting new label into Labels table
* */
public void insertLabel(String label){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, label);
// Inserting Row
db.insert(TABLE_LABELS, null, values);
db.close(); // Closing database connection
}
/**
* Inserting entry data into Fuel Data table
*/
//public void insertFuelData(int vehicleID, String date, String ftype, String brand,
// float price, float kms, float litres) {
public void insertFuelData(ArrayList<String> fuelEntryData) {
SQLiteDatabase dbWrite = this.getWritableDatabase();
ArrayList<String> fuelEntry = fuelEntryData;
ContentValues values = new ContentValues();
//turn array values into individual field values with correct datatype
int vehicleID = getVehicleID(fuelEntry.get(0));
String date = fuelEntry.get(1);
String ftype = fuelEntry.get(2);
String brand = fuelEntry.get(3);
double price = Double.parseDouble((fuelEntry.get(4)));
double kms = Double.parseDouble((fuelEntry.get(5)));
double litres = Double.parseDouble((fuelEntry.get(6)));
//values for calculations
double lper;
double mpg;
//Format calculations to round to one significant digit
DecimalFormat df = new DecimalFormat("###.#");
//calculate Liters/100Kilometres
lper = (100 / (kms / litres));
//calculate U.S. Miles Per Gallon
mpg = (kms / litres) * 2.35;
//Prepare data and Insert row into table
values.put(FIELD_VEHICLEID, vehicleID);
values.put(FIELD_DATE, date);
values.put(FIELD_FTYPE, ftype);
values.put(FIELD_BRAND, brand);
values.put(FIELD_PRICE, price);
values.put(FIELD_KMS, kms);
values.put(FIELD_LITRES, litres);
values.put(FIELD_LPER, df.format(lper));
values.put(FIELD_MPG, df.format(mpg));
dbWrite.insert(TABLE_FUELDATA, null, values);
dbWrite.close();
}
/**
* Getting all labels
* returns list of labels
* */
public List<String> getAllLabels(){
List<String> labels = new ArrayList<String>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_LABELS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
labels.add(cursor.getString(1));
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
db.close();
// returning lables
return labels;
}
/**
* Get entries based on vehicle id
*/
public List<List<String>> getFuelData(int vehicleID) {
//List of Lists - each row/entry of data is a separate List
List<List<String>> fuelDataTable = new ArrayList<List<String>>();
List<String> fuelDataRow = new ArrayList<String>();
//Select Query
String selectQuery = "SELECT * FROM " + TABLE_FUELDATA +
" WHERE vehicle_id = ? ";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, new String[] { String.valueOf(vehicleID) });
// looping through all rows and 9 columns (not incl key) and adding to list
if (cursor.moveToFirst()) {
do {
for(int i = 1; i < 10; i++) {
//doesn't work with non-string values
//fuelDataRow.add(cursor.getString(i));
}
//add each row in its entirety to the List; multi-dimenionsal list
fuelDataTable.add(fuelDataRow);
//empty fuelDataRow
fuelDataRow.clear();
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
db.close();
//return data
return fuelDataTable;
}
public List<String> getFuelDataRows(int vehicleID) {
List<String> fuelDataTable = new ArrayList<String>();
SQLiteDatabase db = this.getReadableDatabase();
//Get data from database table
Cursor c = db.query(TABLE_FUELDATA, fuelDataDisplayCols, " vehicle_id=? ", new String[] { String.valueOf(vehicleID) }, null, null, FIELD_DATE);
//Insert Header row into Array
fuelDataTable.add("Date");
fuelDataTable.add("Type");
fuelDataTable.add("Brand");
fuelDataTable.add("Price");
fuelDataTable.add("KMs");
fuelDataTable.add("Litres");
fuelDataTable.add("L/100");
fuelDataTable.add("MPG");
//Go to beginning of Cursor data and loop through
c.moveToFirst();
while (!c.isAfterLast()) {
//add each cell in the row to List array
fuelDataTable.add(c.getString(c.getColumnIndex(FIELD_DATE)));
fuelDataTable.add(c.getString(c.getColumnIndex(FIELD_FTYPE)));
fuelDataTable.add(c.getString(c.getColumnIndex(FIELD_BRAND)));
fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_PRICE))));
fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_KMS))));
fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_LITRES))));
fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_LPER))));
fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_MPG))));
c.moveToNext();
}
// Make sure to close the cursor
c.close();
db.close();
return fuelDataTable;
}
public int getVehicleID(String label) {
// set variables
SQLiteDatabase dbReader = this.getReadableDatabase();
String vLabel = label;
//Query String
String selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_LABELS +
" WHERE name = ? ";
Cursor c = dbReader.rawQuery(selectQuery, new String[] { vLabel });
//avoid out of bounds exception
c.moveToFirst();
//extract value as integer
int vID = c.getInt(c.getColumnIndex(KEY_ID));
c.close();
return vID;
}
}
Some of it probably looks ugly - this is my first app project and Eclipse auto-populated some of the methods upon creation - but it is working OK in Ice Cream Sandwich.
Thanks for any clues.
db.close() is not needed in public void onCreate(). This will probably fix your problem.

Android populate string array from SQLite database

I have tried to adapt the Google notepad tutorial ( http://developer.android.com/resources/tutorials/notepad/index.html ) for using SQLite databases to store GPS co-ords when the user tags current location. I've had no trouble getting the location added to the database but currently having trouble populating an array from the database in order to draw the locations on the map
private void fillData() {
/**
* Get all of the geotags from the database and populate the strarrlatitude and strarrlongitude arrays
* Also calls 'drawpins' to draw the geotags on the map
*/
Cursor c = mDbHelper.fetchAllNotes();
startManagingCursor(c);
strarrlatitude = new String[] { LocationsDbAdapter.COL_LATITUDE};
System.out.println(strarrlatitude);
strarrlongitude = new String[] { LocationsDbAdapter.COL_LONGITUDE };
drawpins();
}
I'm using a separate class called LocationsDbAdapter for handling database management as demonstrated in the notepad tutorial. The COL_LATITUDE and COL_LONGITUDE variables point to the column titles.
I've used a for loop to determine that nothing seems to be going into the strarrlatitude array but using the SQLite CLI I've checked that the database is being determined
Any help would be most gratefully received - if any more information is required I'll upload it as quick as possible
Many thanks
EDIT: Added the main two classes below for extra reference. I was trying not to overload with too much information but that was an error in judgement.
package com.nick.locationapp;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.AlteredCharSequence;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.nick.androidsoar.R;
public class AndroidSoarActivity extends MapActivity {
/** Called when the activity is first created. */
LinearLayout linearLayout;
MapView mapView;
TextView LocationText;
double dbllatitude;
double dbllongitude;
double dblaltitude;
String debugstring;
String strlatitude = "0";
String strlongitude = "0";
String[] strarrlatitude;
String[] strarrlongitude;
String[] strarrlatitude1 = {"50.0","40.0","43.0","100.0"};
String[] strarrlongitude1 = {"12.4","123.4","60.2","72.0"};
Double[] debuglat = {50.0,40.0,43.0,100.0};
Double[] debuglong = {12.4,123.4,60.2,72.0};
Double dbllat;
Double dbllong;
int intlatitude;
int intlongitude;
private LocationsDbAdapter mDbHelper;
public static final int INSERT_ID = Menu.FIRST;
List<Overlay> mapOverlays;
Drawable drawable;
HelloItemizedOverlay itemizedOverlay;
#Override
protected boolean isRouteDisplayed() {
return false;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Identifies the textview as variable 'LocationText'
LocationText = (TextView)findViewById(R.id.locationtext);
//mDbHelper points to the LocationsDbAdapter class used for handling the database
mDbHelper = new LocationsDbAdapter (this);
mDbHelper.open();
//defines the mapview as variable 'mapView' and enables zoom controls
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapOverlays = mapView.getOverlays();
//points variable 'drawable' to the icon resource of a pushpin, used for marking tags on the map
drawable = this.getResources().getDrawable(R.drawable.pushpin);
//Adds a current location overlay to the map 'mapView' and turns on the map's compass
MyLocationOverlay myLocationOverlay = new MyLocationOverlay(this, mapView);
mapView.getOverlays().add(myLocationOverlay);
myLocationOverlay.enableMyLocation();
myLocationOverlay.enableCompass();
mapView.postInvalidate();
/**
* Code required to receive gps location. Activates GPS provider, and is set to update only after
* at least 10 seconds and a position change of at least 10 metres
*/
LocationListener locationListener = new MyLocationListener();
//setting up the location manager
LocationManager locman = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locman.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10, locationListener);
//fillData();
}
/**
* Generates the menu from the resource 'mainmenu.xml'
*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
return true;
}
/**
* Code to run depending on the menu button pressed
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.new_tag:
createTag();
fillData();
//Toast.makeText(getApplicationContext(), "geotag added to db", Toast.LENGTH_SHORT).show();
return true;
case R.id.draw_pins:
//fillData();
drawpins();
return true;
case R.id.create_tag:
Intent intent = new Intent(AndroidSoarActivity.this, TagCreate.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}
/**
* Create a new geotag pin from the current location
*/
private void createTag() {
//String titleName = "title " + titleNumber++;
mDbHelper.createNote(strlatitude, strlongitude);
Toast.makeText(getApplicationContext(), "geotag of lat: "+dbllatitude+" long: "+dbllongitude+" added to db ", Toast.LENGTH_SHORT).show();
fillData();
}
private void fillData() {
/**
* Get all of the geotags from the database and populate the strarrlatitude and strarrlongitude arrays
* Also calls 'drawpins' to draw the geotags on the map
*/
System.out.println("Fetching data");
Cursor c = mDbHelper.fetchAllNotes();
System.out.println(c.toString());
startManagingCursor(c);
strarrlatitude = new String[] { LocationsDbAdapter.COL_LATITUDE };
//System.out.println(strarrlatitude);
strarrlongitude = new String[] { LocationsDbAdapter.COL_LONGITUDE };
}
/**
* Creates an array of geopoints, pulling the locations from strarrlatitude and strarrlongitude
* and creates a mapview overlay using the geopoints
*/
private void drawpins() {
itemizedOverlay = new HelloItemizedOverlay(drawable);
GeoPoint[] mapPoints = new GeoPoint[strarrlatitude.length];
OverlayItem[] mapItems = new OverlayItem[strarrlatitude.length];
for(int i=1; i<strarrlatitude.length;i++){
dbllat = Double.parseDouble(strarrlatitude[i]);
dbllong = Double.parseDouble(strarrlongitude[i]);
System.out.println(i);
mapPoints[i] = new GeoPoint((int) (dbllat * 1E6), (int) (dbllong * 1E6));
mapItems[i] = new OverlayItem(mapPoints[i], "", "");
itemizedOverlay.addOverlay(mapItems[i]);
mapOverlays.add(itemizedOverlay);
}
}
private final class MyLocationListener implements LocationListener {
/**
* Code to run when the listener receives a new location
*/
#Override
public void onLocationChanged(Location locFromGps) {
Toast.makeText(getApplicationContext(), "Location changed, Lat: "+locFromGps.getLatitude()+" Long: "+ locFromGps.getLongitude(), Toast.LENGTH_SHORT).show();
//LocationText.setText("Your Location: Latitude " +locFromGps.getLatitude() + " Longitude: " +locFromGps.getLongitude());
dbllatitude = locFromGps.getLatitude();
dbllongitude = locFromGps.getLongitude();
dblaltitude = locFromGps.getAltitude();
strlatitude = Double.toString(dbllatitude);
strlongitude = Double.toString(dbllongitude);
dblaltitude = (dblaltitude / 0.3048);
LocationText.setText("Your Location: Latitude " + dbllatitude + " Longitude: " +dbllongitude + " Altitude " + dblaltitude);
}
#Override
public void onProviderDisabled(String provider) {
// called when the GPS provider is turned off (user turning off the GPS on the phone)
}
#Override
public void onProviderEnabled(String provider) {
// called when the GPS provider is turned on (user turning on the GPS on the phone)
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// called when the status of the GPS provider changes
}
}
}
/**
* Following class has been adapted from Google's Android Notepad tutorial: http://developer.android.com/resources/tutorials/notepad/index.html
*
*/
package com.nick.locationapp;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class LocationsDbAdapter {
public static final String COL_LATITUDE = "latitude";
public static final String COL_LONGITUDE = "longitude";
//public static final String KEY_NOTE = "note";
public static final String COL_TITLE = "title";
public static final String COL_ROWID = "_id";
//public static final String TABLE_LOC = "locations";
private static final String TAG = "LocationsDbAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
/**
* Database creation sql statement
*/
private static final String DATABASE_CREATE =
"CREATE TABLE locations (_id integer primary key autoincrement, "
+ "latitude text not null, longitude text not null);";
private static final String DATABASE_NAME = "data";
private static final String DATABASE_TABLE = "locations";
private static final int DATABASE_VERSION = 1;
private final Context mCtx;
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* SQL for creating the table. Table and column names are declared as variables
*/
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+DATABASE_TABLE+" ("+COL_ROWID+ " INTEGER PRIMARY KEY AUTOINCREMENT, "+COL_LATITUDE+ " TEXT, "+COL_LONGITUDE+" TEXT "+COL_TITLE+" TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS location");
onCreate(db);
}
}
public LocationsDbAdapter(Context ctx) {
this.mCtx = ctx;
}
public LocationsDbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void close() {
mDbHelper.close();
}
/**
* Code for adding latitude and longitude into the database
* #param latitude
* #param longitude
* #return
*/
public long createNote(String latitude, String longitude) {
ContentValues geotagValues = new ContentValues();
geotagValues.put(COL_LATITUDE, latitude);
geotagValues.put(COL_LONGITUDE, longitude);
//geotagValues.put(COL_TITLE, title);
return mDb.insert(DATABASE_TABLE, null, geotagValues);
}
/**
* Query to return all data
* #return
*/
public Cursor fetchAllNotes() {
return mDb.query(DATABASE_TABLE, new String[] {COL_ROWID, COL_LATITUDE, COL_LONGITUDE}, null, null, null, null, null);
}
}
*
public void getData()
{
List<String> labels = new ArrayList<String>();
placeData = new PlaceDataSQL(MainActivity.this);
String selectQuery = "SELECT * FROM xmlTable;";
SQLiteDatabase db = placeData.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
{
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
labels.add(cursor.getString(1));
Log.i("imagespath",arr[i]);
i++;
} while (cursor.moveToNext());
}
cursor.close();enter code here
db.close();
}
}
*

Categories