I am using a SMSReceiver class which receives an sms and then sends the sms as an extra to my main activity to use in the map application. In my onReceive method I toast the extra and I get the value perfectly fine, but when I try use the variable later down my code to reverse geoCode to get the coordinates from the address then suddenly the global variable is null again :(
The method is called showOnMapClicked on line 324 where the variable is null again.
The sms is being sent from the DDMS.
Somebody please help, I just cant figure it out!
OnReceive Class:
package com.example.maps;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
import android.content.Intent;
public class SMSReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//Adding bundle extras to be used by the main class
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "SMS from ";
//Adding the sms to the array to be stored
if (bundle != null)
{
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
if (i == 0)
{
//Appending the information to the string to be displayed
str += msgs[i].getOriginatingAddress();
str += ": \n";
}
str += msgs[i].getMessageBody().toString();
}
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
//Creating the new intent
Intent mainActivityIntent = new Intent(context, MainActivity.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mainActivityIntent);
//Making the intent broadcast to the main class and putting the extra in to be displayed
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
//Setting the name of the string to "sms"
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
//Stops the sms from going directly into the inbox
this.abortBroadcast();
}
}
}
Main Activity Class:
package com.example.maps;
//Daniel Tromp - Assignment 2 - 12002076
//Imports for DAYS!
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import com.example.maps.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.text.InputFilter;
import android.text.InputType;
import android.text.method.DigitsKeyListener;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
//Implementing all the needed services
public class MainActivity extends Activity implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
// Initializing the needed globals
Location mLocation;
String addressSms;
String addressText;
public GoogleMap mMap;
private TextView mAddress;
private ProgressBar mActivityIndicator;
private LocationClient mLocationClient;
BroadcastReceiver smsSentReceiver, smsDeliveredReceiver;
IntentFilter intentFilter;
// Milliseconds per second
private static final int MILLISECONDS_PER_SECOND = 1000;
// Update frequency in seconds
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
// Update frequency in milliseconds
private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND
* UPDATE_INTERVAL_IN_SECONDS;
// The fastest update frequency, in seconds
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
// A fast frequency ceiling in milliseconds
private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND
* FASTEST_INTERVAL_IN_SECONDS;
// Define an object that holds accuracy and frequency parameters
private LocationRequest mLocationRequest;
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
#Override
//On receiving a message, the textview is set to the sms message
public void onReceive(Context context, Intent intent) {
addressSms = intent.getStringExtra("sms");
//Toasting the variable where it displays my sms message
Toast.makeText(getBaseContext(), addressSms, Toast.LENGTH_LONG).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpMapIfNeeded();
mAddress = (TextView) findViewById(R.id.address);
// As the app loads, the address bar will be displayed
mActivityIndicator = (ProgressBar) findViewById(R.id.address_progress);
// Setting the map type to be Hybrid
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
/*
* Create a new location client, using the enclosing class to handle
* callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
//Creating the new intent
intentFilter = new IntentFilter();
intentFilter.addAction("SMS_RECEIVED_ACTION");
registerReceiver(intentReceiver, intentFilter);
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the
// map.
if (mMap == null) {
mMap = ((MapFragment) getFragmentManager().findFragmentById(
R.id.map)).getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
// The Map is verified. It is now safe to manipulate the map.
}
}
}
// When the application is started
#Override
protected void onStart() {
super.onStart();
// Connect the client.
mLocationClient.connect();
}
private class GetAddressTask extends AsyncTask<Location, Void, String> {
Context mContext;
public GetAddressTask(Context context) {
super();
mContext = context;
}
protected String doInBackground(Location... params) {
Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());
// Get the current location from the input parameter list
Location loc = params[0];
// Create a list to contain the result address
List<Address> addresses = null;
try {
/*
* Return 1 address.
*/
addresses = geocoder.getFromLocation(loc.getLatitude(),
loc.getLongitude(), 1);
} catch (IOException e1) {
Log.e("LocationSampleActivity",
"IO Exception in getFromLocation()");
e1.printStackTrace();
return ("IO Exception trying to get address");
} catch (IllegalArgumentException e2) {
// Error message to post in the log
String errorString = "Illegal arguments "
+ Double.toString(loc.getLatitude()) + " , "
+ Double.toString(loc.getLongitude())
+ " passed to address service";
Log.e("LocationSampleActivity", errorString);
e2.printStackTrace();
return errorString;
}
// If the reverse geocode returned an address
if (addresses != null && addresses.size() > 0) {
// Get the first address
Address address = addresses.get(0);
/*
* Format the first line of address (if available), city, and
* country name.
*/
addressText = String.format(
"%s, %s, %s",
// If there's a street address, add it
address.getMaxAddressLineIndex() > 0 ? address
.getAddressLine(0) : "",
// Locality is usually a city
address.getLocality(),
// The country of the address
address.getCountryName());
// Return the text
return addressText;
} else {
return "No address found";
}
}
protected void onPostExecute(String address) {
// Set activity indicator visibility to "gone"
mActivityIndicator.setVisibility(View.GONE);
// Display the results of the lookup.
mAddress.setText(address);
}
}
// When the connection is made to get live updates
public void onConnected(Bundle dataBundle) {
// Display the connection status
Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
// Start periodic updates
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
// When the new coordinates are put into the DDMS, the map will change to
// that location and get the new address
public void onLocationChanged(Location location) {
// Report to the UI that the location was updated
LatLng latlng = new LatLng(location.getLatitude(),
location.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng));
mActivityIndicator.setVisibility(View.VISIBLE);
/*
* Reverse geocoding is long-running and synchronous. Run it on a
* background thread. Pass the current location to the background task.
* When the task finishes, onPostExecute() displays the address.
*/
(new GetAddressTask(this)).execute(location);
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onDisconnected() {
}
// Click on button to get the read me file to know how to use the
// application
public void readMeClicked(View v) {
// Create a dialog to pop up and explain the application to the user
AlertDialog alertDialog = new AlertDialog.Builder(this).create(); // Read
// Update
alertDialog.setTitle("Read Me");
alertDialog
.setMessage("My app was created to be able to quickly send out an emergency SMS to a certain individual which will contain the emergency message as well as their current location. By using the DDMS, the coordinates can be input and then my app will go to that specific location and pull the most correct address of that location");
// Making the dialog show
alertDialog.show();
}
public void getFromLocationClicked(View v) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
MainActivity.this);
// Setting Dialog Title
alertDialog.setTitle("Emergency SMS");
// Setting Dialog Message
alertDialog.setMessage("Enter Emergency Contact Number");
final EditText input = new EditText(MainActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
alertDialog.setView(input);
// Setting Positive "Continue" Button
alertDialog.setPositiveButton("Continue",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String testing = input.getText().toString();
getFromLocation(testing);
}
});
// Setting Negative "Cancel" Button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
};
public void getFromLocation(String strAddress) {
Geocoder coder = new Geocoder(this);
List<Address> address;
try {
address = coder.getFromLocationName(strAddress, 5);
if (address != null) {
Address location = address.get(0);
double recLat = location.getLatitude();
double recLng = location.getLongitude();
LatLng p = new LatLng(recLat, recLng);
Toast.makeText(getBaseContext(), p + "", Toast.LENGTH_LONG)
.show();
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(p, 16));
}
} catch (IOException ie) {
ie.printStackTrace();
}
}
//Showing the value when the show button is clicked
public void showOnMapClicked(View v)
{
//When it toasts, the addressSms value is now null!??
Toast.makeText(getBaseContext(), addressSms, Toast.LENGTH_LONG).show();
//getFromLocation(addressSms);
}
public void showToast(String message)
{
String test = message;
Toast.makeText(getBaseContext(), test, Toast.LENGTH_LONG).show();
}
// Click the button to start to generate the emergency SMS
public void sendAddressClicked(final View v) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
MainActivity.this);
// Setting Dialog Title
alertDialog.setTitle("Emergency SMS");
// Setting Dialog Message
alertDialog.setMessage("Enter Emergency Contact Number");
final EditText input = new EditText(MainActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
alertDialog.setView(input);
input.setFilters(new InputFilter[] {
// Maximum 2 characters.
new InputFilter.LengthFilter(10),
// Digits only.
DigitsKeyListener.getInstance(), // Not strictly needed, IMHO.
});
// Setting Positive "Continue" Button
alertDialog.setPositiveButton("Continue",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Setting the SMS message and adding the current
// location which is gathered by the map.
String textMessage = input.getText().toString();
// Checking if the phone number is not blank
if (textMessage.isEmpty()) {
// If the phone number is not entered
Toast.makeText(getBaseContext(),
"Cannot be blank. Enter phone number.",
Toast.LENGTH_LONG).show();
sendAddressClicked(v);
}
else {
enterMessage(textMessage);
}
}
});
// Setting Negative "Cancel" Button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
};
// Method to send the emergency method and the current location
private void sendSMS(String phoneNumber, String message) {
// Sending the sms to the emulator number input
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
}
// Once the user has input the number, the message now will be asked for
public void enterMessage(final String number) {
// Creating the dialog to input the emergency message
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
MainActivity.this);
// Setting Dialog Title
alertDialog.setTitle("Emergency SMS");
// Setting Dialog Message
alertDialog.setMessage("Enter Emergency SMS");
final EditText input = new EditText(MainActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
alertDialog.setView(input);
input.setInputType(InputType.TYPE_CLASS_TEXT);
// Setting Positive "SEND SMS" Button
alertDialog.setPositiveButton("SEND SMS",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to execute after dialog
// Setting the SMS message and adding the current
// location which is gathered by the map.
String textMessage = input.getText().toString();
String SMS = textMessage + "\n\n"
+ "My Current Address Is: " + addressText;
String phoneNumber = number;
// Checking to see if the SMS is blank
if (textMessage.isEmpty()) {
Toast.makeText(getBaseContext(),
"Cannot be blank. Enter emergency SMS.",
Toast.LENGTH_LONG).show();
enterMessage(phoneNumber);
}
else {
// Sending the variables through to the sendSMS
// method to be sent
sendSMS(phoneNumber, SMS);
}
}
});
// Setting Negative "Cancel" Button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to execute after dialog
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
};
}
Try overriding the onSaveInstanceState(Bundle bundle) method in your MainActivity and use logs to see if it is getting called before your data is getting wiped out. I suspect that you'll see it is getting called. If so, just save your 'globals' in the bundle and retrieve them by overriding the onRestoreInstanceState(Bundle bundle)
The DOC should help you with how to save and restore. Whenever the activity needs to be killed for memory or orientation change, onCreate will be called and the 'globals' can be lost that way.
This might help with more details.
Related
UPDATE: I needed to override the onDestroy method to close the Database Helper class object. Works fine now. Just add this in any activity where you create an object of your SQLiteOpenHelper class.
Database dbHelper; //in class
dbHelper = new Database(this, "pulling data",null,1); //in onCreate
#Override
protected void onDestroy()
{
super.onDestroy();
dbHelper.close();
}
I create and update a database from a fragment with data that comes in about every 2 seconds from sensors that are connected over Bluetooth to my Android app.
I go to different activities in my app and those activities should be able to read from the database to display the data in a list/textview, but the issue is that the context in which the database was created and is getting updated is from a fragment. Is there a way to make it so that all activities can read from the database?
I created a class that extends SQLiteOpenHelper, where you can access functions to do CRUD operations, but once I go into another activity and I query the database the cursor pulls nothing up although I inserted and am updating the database in the background from a fragment.
Heads up, I'm pretty new to Android dev and have looked at other questions/solutions but nothing works for me. Appreciate any tutorials or advice to get going, thanks!
Below is my SQLiteOpenHelper class:
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" } );
}
}
}
Below is the fragment that interacts with the class from above to insert/update data in the database. I took the Google BluetoothChat app and modified it to work for my intended purpose. This fragment interacts with the Database class in the handler for MESSAGE_READ. I parse the data sent to me, then pass it as parameters to the Database function updateSensorData where it takes care of inserting then thereafter updating the data.
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);
}
}
Below is an example of one of the different classes that needs to access the information in the database. I test it with the checkExist() function and it returns false although in the fragment I do successfully insert then update the sensor data. This is where my problem lies, not sure why it isn't pulling anything from the database
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();
}
}
Extends LoaderManager.LoaderCallbacks in your activity to load the data from the data base.
For more information you can read that:
https://developer.android.com/guide/components/loaders.html
See this:
http://guides.codepath.com/android/local-databases-with-sqliteopenhelper
I would recommend you to use the singleton pattern to avoid leak and to re-allocate the db each time.
It's highly recommended to use startTransaction and endTransaction as described in the link above.
If it still doesn't work, i also recommend to you to use Loaders as #Bruno suggested.
Regardless your question, just a small potential bug fix - In Database class in function updateSensorData you forgot to close the Cursor in the else flow.
on line 370 i need a way to look for a string of 'f's' in the advertisement data from a TI CC2650. I found this template online but I'm looking for specific advertising data. Please let me know what string array I need to look at to find this.
package net.jmodwyer.beacon.beaconPoC;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.text.util.Linkify;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import net.jmodwyer.ibeacon.ibeaconPoC.R;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.utils.UrlBeaconUrlCompressor;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
/**
* Adapted from original code written by D Young of Radius Networks.
* #author dyoung, jodwyer
*
*/
public class ScanActivity extends Activity implements BeaconConsumer,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
// Constant Declaration
private static final String PREFERENCE_SCANINTERVAL = "scanInterval";
private static final String PREFERENCE_TIMESTAMP = "timestamp";
private static final String PREFERENCE_POWER = "power";
private static final String PREFERENCE_PROXIMITY = "proximity";
private static final String PREFERENCE_RSSI = "rssi";
private static final String PREFERENCE_MAJORMINOR = "majorMinor";
private static final String PREFERENCE_UUID = "uuid";
private static final String PREFERENCE_INDEX = "index";
private static final String PREFERENCE_LOCATION = "location";
private static final String PREFERENCE_REALTIME = "realTimeLog";
private static final String MODE_SCANNING = "Stop Scanning";
private static final String MODE_STOPPED = "Start Scanning";
protected static final String TAG = "ScanActivity";
/*
* Define a request code to send to Google Play services
* This code is returned in Activity.onActivityResult
*/
private final static int
CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private FileHelper fileHelper;
private BeaconManager beaconManager;
private Region region;
private int eventNum = 1;
// This StringBuffer will hold the scan data for any given scan.
private StringBuffer logString;
// Preferences - will actually have a boolean value when loaded.
private Boolean index;
private Boolean location;
private Boolean uuid;
private Boolean majorMinor;
private Boolean rssi;
private Boolean proximity;
private Boolean power;
private Boolean timestamp;
private String scanInterval;
// Added following a feature request from D.Schmid.
private Boolean realTimeLog;
// LocationClient for Google Play Location Services
LocationClient locationClient;
private ScrollView scroller;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
verifyBluetooth();
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
BeaconScannerApp app = (BeaconScannerApp)this.getApplication();
beaconManager = app.getBeaconManager();
//beaconManager.setForegroundScanPeriod(10);
region = app.getRegion();
beaconManager.bind(this);
locationClient = new LocationClient(this, this, this);
fileHelper = app.getFileHelper();
scroller = (ScrollView)ScanActivity.this.findViewById(R.id.scanScrollView);
editText = (EditText)ScanActivity.this.findViewById(R.id.scanText);
// Initialise scan button.
getScanButton().setText(MODE_STOPPED);
}
#Override
public void onResume() {
super.onResume();
beaconManager.bind(this);
}
#Override
public void onPause() {
super.onPause();
// Uncommenting the following leak prevents a ServiceConnection leak when using the back
// arrow in the Action Bar to come out of the file list screen. Unfortunately it also kills
// background scanning, and as I have no workaround right now I'm settling for the lesser of
// two evils.
// beaconManager.unbind(this);
}
public String getCurrentLocation() {
/** Default "error" value is set for location, will be overwritten with the correct lat and
* long values if we're ble to connect to location services and get a reading.
*/
String location = "Unavailable";
if (locationClient.isConnected()) {
Location currentLocation = locationClient.getLastLocation();
if (currentLocation != null) {
location = Double.toString(currentLocation.getLatitude()) + "," +
Double.toString(currentLocation.getLongitude());
}
}
return location;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public void onBeaconServiceConnect() {}
/**
*
* #param view
*/
public void onScanButtonClicked(View view) {
toggleScanState();
}
// Handle the user selecting "Settings" from the action bar.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.Settings:
// Show settings
Intent api = new Intent(this, AppPreferenceActivity.class);
startActivityForResult(api, 0);
return true;
case R.id.action_listfiles:
// Launch list files activity
Intent fhi = new Intent(this, FileHandlerActivity.class);
startActivity(fhi);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Start and stop scanning, and toggle button label appropriately.
*/
private void toggleScanState() {
Button scanButton = getScanButton();
String currentState = scanButton.getText().toString();
if (currentState.equals(MODE_SCANNING)) {
stopScanning(scanButton);
} else {
startScanning(scanButton);
}
}
/**
* start looking for beacons.
*/
private void startScanning(Button scanButton) {
// Set UI elements to the correct state.
scanButton.setText(MODE_SCANNING);
((EditText)findViewById(R.id.scanText)).setText("");
// Reset event counter
eventNum = 1;
// Get current values for logging preferences
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
HashMap <String, Object> prefs = new HashMap<String, Object>();
prefs.putAll(sharedPrefs.getAll());
index = (Boolean)prefs.get(PREFERENCE_INDEX);
location = (Boolean)prefs.get(PREFERENCE_LOCATION);
uuid = (Boolean)prefs.get(PREFERENCE_UUID);
majorMinor = (Boolean)prefs.get(PREFERENCE_MAJORMINOR);
rssi = (Boolean)prefs.get(PREFERENCE_RSSI);
proximity = (Boolean)prefs.get(PREFERENCE_PROXIMITY);
power = (Boolean)prefs.get(PREFERENCE_POWER);
timestamp = (Boolean)prefs.get(PREFERENCE_TIMESTAMP);
scanInterval = (String)prefs.get(PREFERENCE_SCANINTERVAL);
realTimeLog = (Boolean)prefs.get(PREFERENCE_REALTIME);
// Get current background scan interval (if specified)
if (prefs.get(PREFERENCE_SCANINTERVAL) != null) {
beaconManager.setBackgroundBetweenScanPeriod(Long.parseLong(scanInterval));
}
logToDisplay("Scanning...");
// Initialise scan log
logString = new StringBuffer();
//Start scanning again.
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Iterator <Beacon> beaconIterator = beacons.iterator();
while (beaconIterator.hasNext()) {
Beacon beacon = beaconIterator.next();
// Debug - logging a beacon - checking background logging is working.
System.out.println("Logging another beacon.");
logBeaconData(beacon);
}
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
// TODO - OK, what now then?
}
}
/**
* Stop looking for beacons.
*/
private void stopScanning(Button scanButton) {
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
// TODO - OK, what now then?
}
String scanData = logString.toString();
if (scanData.length() > 0) {
// Write file
fileHelper.createFile(scanData);
// Display file created message.
Toast.makeText(getBaseContext(),
"File saved to:" + getFilesDir().getAbsolutePath(),
Toast.LENGTH_SHORT).show();
scanButton.setText(MODE_STOPPED);
} else {
// We didn't get any data, so there's no point writing an empty file.
Toast.makeText(getBaseContext(),
"No data captured during scan, output file will not be created.",
Toast.LENGTH_SHORT).show();
scanButton.setText(MODE_STOPPED);
}
}
/**
*
* #return reference to the start/stop scanning button
*/
private Button getScanButton() {
return (Button)findViewById(R.id.scanButton);
}
/**
*
* #param beacon The detected beacon
*/
private void logBeaconData(Beacon beacon) {
StringBuilder scanString = new StringBuilder();
if (index) {
scanString.append(eventNum++);
}
if (beacon.getServiceUuid() == 0xfeaa) {
if (beacon.getBeaconTypeCode() == 0x00) {
scanString.append(" Eddystone-UID -> ");
scanString.append(" Namespace : ").append(beacon.getId1());
scanString.append(" Identifier : ").append(beacon.getId2());
logEddystoneTelemetry(scanString, beacon);
} else if (beacon.getBeaconTypeCode() == 0x10) {
String url = UrlBeaconUrlCompressor.uncompress(beacon.getId1().toByteArray());
scanString.append(" Eddystone-URL -> " + url);
} else if (beacon.getBeaconTypeCode() == 0x20) {
scanString.append(" Eddystone-TLM -> ");
logEddystoneTelemetry(scanString, beacon);
}
} else {
// Just an old fashioned iBeacon or AltBeacon...
logGenericBeacon(scanString, beacon);
}
logToDisplay(scanString.toString());
scanString.append("\n");
// Code added following a feature request by D.Schmid - writes a single entry to a file
// every time a beacon is detected, the file will only ever have one entry as it will be
// recreated on each call to this method.
// Get current background scan interval (if specified)
if (realTimeLog) {
// We're in realtime logging mode, create a new log file containing only this entry.
fileHelper.createFile(scanString.toString(), "realtimelog.txt");
}
logString.append(scanString.toString());
}
/**
* Logs iBeacon & AltBeacon data.
*/
private void logGenericBeacon(StringBuilder scanString, Beacon beacon) {
// Comment stuff out for whatever reason
/*
if (location) {
scanString.append(" Location: ").append(getCurrentLocation()).append(" ");
}
`
*/
if (uuid) {
scanString.append(" UUID: ").append(beacon.getId1());
if (beacon.getId1().equals("ffffffff-ffff-ffff-ffff-ffffffffffff ")){
scanString.append("WE DID IT!!!!!!!!!!!");
}else{
scanString.append(" WE DID NOT DO IT =( ");
}
/*
if ((beacon.getId1()).equals ("f")){
scanString.append("WE DID IT!!!!!!!!!!!");
}else{
scanString.append(" WE DID NOT DO IT!!!!!!!!!!! ");
}
*/
}
// Making if statements to test for advertising data
/*
if (majorMinor) {
scanString.append(" Maj. Mnr.: ");
if (beacon.getId2() != null) {
scanString.append(beacon.getId2());
}
scanString.append("-");
if (beacon.getId3() != null) {
scanString.append(beacon.getId3());
}
}
if (rssi) {
scanString.append(" RSSI: ").append(beacon.getRssi());
}
if (proximity) {
scanString.append(" Proximity: ").append(BeaconHelper.getProximityString(beacon.getDistance()));
}
if (power) {
scanString.append(" Power: ").append(beacon.getTxPower());
}
if (timestamp) {
scanString.append(" Timestamp: ").append(BeaconHelper.getCurrentTimeStamp());
} */
}
private void logEddystoneTelemetry(StringBuilder scanString, Beacon beacon) {
// Do we have telemetry data?
if (beacon.getExtraDataFields().size() > 0) {
long telemetryVersion = beacon.getExtraDataFields().get(0);
long batteryMilliVolts = beacon.getExtraDataFields().get(1);
long pduCount = beacon.getExtraDataFields().get(3);
long uptime = beacon.getExtraDataFields().get(4);
scanString.append(" Telemetry version : " + telemetryVersion);
scanString.append(" Uptime (sec) : " + uptime);
scanString.append(" Battery level (mv) " + batteryMilliVolts);
scanString.append(" Tx count: " + pduCount);
}
}
/**
*
* #param line
*/
private void logToDisplay(final String line) {
runOnUiThread(new Runnable() {
public void run() {
editText.append(line + "\n");
// Temp code - don't really want to do this for every line logged, will look for a
// workaround.
Linkify.addLinks(editText, Linkify.WEB_URLS);
scroller.fullScroll(View.FOCUS_DOWN);
}
});
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
/* Location services code follows */
#Override
protected void onStart() {
super.onStart();
// Connect the client.
locationClient.connect();
}
#Override
protected void onStop() {
// Disconnect the client.
locationClient.disconnect();
super.onStop();
}
#Override
public void onConnected(Bundle dataBundle) {
// Uncomment the following line to display the connection status.
// Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
}
#Override
public void onDisconnected() {
// Display the connection status
Toast.makeText(this, "Disconnected. Please re-connect.",
Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
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 {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
Toast.makeText(getBaseContext(),
"Location services not available, cannot track device location.",
Toast.LENGTH_SHORT).show();
}
}
// Define a DialogFragment that displays the error dialog
public static class ErrorDialogFragment extends DialogFragment {
// Global field to contain the error dialog
private Dialog mDialog;
// Default constructor. Sets the dialog field to null
public ErrorDialogFragment() {
super();
mDialog = null;
}
// Set the dialog to display
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
// Return a Dialog to the DialogFragment.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
/*
* Handle results returned to the FragmentActivity
* by Google Play services
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
// Decide what to do based on the original request code
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST :
/*
* If the result code is Activity.RESULT_OK, try
* to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK :
/*
* TODO - Try the request again
*/
break;
}
}
}
}
Need to cast to string first .toString
if (uuid) {
scanString.append(" UUID: ").append(beacon.getId1());
// Making if statements to look for all f's in advertising data
if (beacon.getId1().toString().equals(Str1)){
scanString.append("\nAlarm ACTIVATED\n");
}else{
scanString.append("\n Alarm NOT active\n");
}
}
i am trying out below code everything works fine when net is connected
here is the workflow
there is a main activity from where on button click this activity should open
it would do the parsing part and then go to next list activity.in case there is a back press or this activity is closed the asynctask should stop using
loader.cancel(true);
this would work perfectly if net is available and tested the issue happens when dont have internet connection
the alert box shows and it goes to the first activity then it crashes
i want the alert box to show and app should not crash and go back to first -->mainactivity
i have refereed this
http://techiedreams.com/android-simple-rss-reader/
How to end AsyncTask onBackPress()
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import com.parser.DOMParser;
import com.parser.RSSFeed;
public class SplashActivity extends Activity {
//private String RSSFEEDURL = "http://www.mobilenations.com/rss/mb.xml";
RSSFeed feed;
private AsyncLoadXMLFeed loader;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Intent i = getIntent();
int position = i.getExtras().getInt("position");
String[] country = i.getStringArrayExtra("country");
//Toast.makeText(getApplicationContext(), country[position], Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(), country[position], Toast.LENGTH_SHORT).show();
String name = i.getStringExtra("name");
//Toast.makeText(getApplicationContext(), name, Toast.LENGTH_SHORT).show();
ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (conMgr.getActiveNetworkInfo() == null) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(
"Unable to reach server, \nPlease check your connectivity.")
.setTitle("TD RSS Reader")
.setCancelable(false)
.setPositiveButton("Exit",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int id) {
//loader.cancel(true);
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
} else {
// Connected - Start parsing
loader = new AsyncLoadXMLFeed();
loader.execute();
//new AsyncLoadXMLFeed().execute();
}
}
private class AsyncLoadXMLFeed extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
// Obtain feed
DOMParser myParser = new DOMParser();
Intent i = getIntent();
int position = i.getExtras().getInt("position");
String[] country = i.getStringArrayExtra("country");
String name = i.getStringExtra("name");
//feed = myParser.parseXml(RSSFEEDURL);
feed = myParser.parseXml("http://"+name+".blogspot.com//feeds/posts/default/-/" + country[position] + "?alt=rss");
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Bundle bundle = new Bundle();
bundle.putSerializable("feed", feed);
// launch List activity
Intent intent = new Intent(SplashActivity.this, ListActivity.class);
intent.putExtras(bundle);
startActivity(intent);
// kill this activity
finish();
}
}
#Override
public void onBackPressed() {
finish();
}
#Override
public void onDestroy(){
super.onDestroy();
// Cancel the task
loader.cancel(true);
}
My guess it crashes with NullPointerException.
It is because if you don't have network connectivity you don't create AsyncLoadXMLFeed instance.
So when onDestroy() happened and you call loader.cancel(true); it throws this Exception.
finally did this
thanks anatol needed to check loader != null
#Override
public void onDestroy(){
super.onDestroy();
// Cancel the task
if(loader != null && loader.getStatus() != AsyncTask.Status.FINISHED) {
loader.cancel(true);
}
//loader.cancel(true);
}
The best and simplest solution for handle this issue is that use try catch block in your onPost execute() in async task. like this
#Override
protected void onPostExecute(String s) {
try {
super.onPostExecute(s);
loading.dismiss();
}catch (Exception ex){
Toast.makeText(UserLogin.this, "Something is going wrong, please try again!", Toast.LENGTH_LONG).show();
}
}
simply this will prevent your app from crash.
I have singlePlaceActivity class from which I want to pass string data like name ,address which I got in OnpostExecute to another Email activity. My singlePlace activity succesfully starts the email activity but I didn't receive putExtra string data in Email activity using getextra method and my string data name,address,phone don't have null values as I verified from logcat.
SinglePlaceActivity:
package info.androidhive.slidingmenu;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.widget.TextView;
public class SinglePlaceActivity extends Activity {
// flag for Internet connection status
Boolean isInternetPresent = false;
// Connection detector class
ConnectionDetector cd;
// Alert Dialog Manager
AlertDialogManager alert = new AlertDialogManager();
// Google Places
GooglePlaces googlePlaces;
// Place Details
PlaceDetails placeDetails;
// Progress dialog
ProgressDialog pDialog;
// KEY Strings
// public static String KEY_REFERENCE = "reference"; // id of the place
public static String reference_value = "reference";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.single_place);
Intent i = getIntent();
// Place referece id
String reference = i.getStringExtra(reference_value);
// Calling a Async Background thread
new LoadSinglePlaceDetails().execute(reference);
}
/**
* Background Async Task to Load Google places
* */
class LoadSinglePlaceDetails extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SinglePlaceActivity.this);
pDialog.setMessage("Passing Restaurent details to Email ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting Profile JSON
* */
protected String doInBackground(String... args) {
String reference = args[0];
// creating Places class object
googlePlaces = new GooglePlaces();
// Check if used is connected to Internet
try {
placeDetails = googlePlaces.getPlaceDetails(reference);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed Places into LISTVIEW
* */
if(placeDetails != null){
String status = placeDetails.status;
// check place deatils status
// Check for all possible status
if(status.equals("OK")){
if (placeDetails.result != null) {
String name = placeDetails.result.name;
String address = placeDetails.result.formatted_address;
String phone = placeDetails.result.formatted_phone_number;
String latitude = Double.toString(placeDetails.result.geometry.location.lat);
String longitude = Double.toString(placeDetails.result.geometry.location.lng);
Intent in = new Intent(getApplicationContext(),Email.class);
in.putExtra("nameValue",name );
in.putExtra("addValue",address );
in.putExtra("urlValue",phone );
startActivity(in);
Log.d("Place ", name + address + phone + latitude + longitude);
}
}
else if(status.equals("ZERO_RESULTS")){
alert.showAlertDialog(SinglePlaceActivity.this, "Near Places",
"Sorry no place found.",
false);
}
else if(status.equals("UNKNOWN_ERROR"))
{
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry unknown error occured.",
false);
}
else if(status.equals("OVER_QUERY_LIMIT"))
{
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry query limit to google places is reached",
false);
}
else if(status.equals("REQUEST_DENIED"))
{
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured. Request is denied",
false);
}
else if(status.equals("INVALID_REQUEST"))
{
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured. Invalid Request",
false);
}
else
{
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured.",
false);
}
}else{
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured.",
false);
}
}
});
}
}
}
And this is my second receiving activity that is Email activity
Email.java
package info.androidhive.slidingmenu;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class Email extends Activity implements View.OnClickListener {
EditText personsEmail, rname, radd, rurl, yourmsg;
String emailAdd, beginning, stupidAction, hatefulAct, address;
Button sendEmail;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.email);
//String beginning = getIntent().getStringExtra("extraname") ;//returns null if nothing
// String address = getIntent().getStringExtra("extraname2");
//String stupidAction = getIntent().getStringExtra("extraname2");
beginning = getIntent().getStringExtra("nameValue");
address = getIntent().getStringExtra("addValue");
stupidAction= getIntent().getStringExtra("urlValue");
// beginning = intent.getStringExtra("nameValue");
//address = intent.getStringExtra("addValue");
// stupidAction = intent.getStringExtra("urlValue");
initializeVars();
sendEmail.setOnClickListener(this);
}
private void initializeVars() {
// TODO Auto-generated method stub
personsEmail = (EditText) findViewById(R.id.etEmails);
rname = (EditText) findViewById(R.id.etIntro);
radd = (EditText) findViewById(R.id.etName);
rurl = (EditText) findViewById(R.id.etThings);
yourmsg = (EditText) findViewById(R.id.etAction);
sendEmail = (Button) findViewById(R.id.bSentEmail);
}
public void onClick(View v) {
// TODO Auto-generated method stub
convertEditTextVarsIntoStringsAndYesThisIsAMethodWeCreated();
String emailaddress[] = { emailAdd };
String message = "Restaurent Name:"+ beginning
+ " Restaurent Address:"+ address
+ "Click for more details:" + stupidAction
+ "Message:" + hatefulAct;
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, emailaddress);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT," Restaurent Recommendation");
emailIntent.setType("plain/text");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
startActivity(emailIntent);
}
private void convertEditTextVarsIntoStringsAndYesThisIsAMethodWeCreated() {
// TODO Auto-generated method stub
emailAdd = personsEmail.getText().toString();
beginning = rname.getText().toString();
address = radd.getText().toString();
stupidAction = rurl.getText().toString();
hatefulAct = yourmsg.getText().toString();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
Try bundle to pass and receive data,
Intent intent = new Intent(first.this, second.class);
Bundle bundle = new Bundle();
bundle.putInt("index", index);
intent.putExtras(bundle);
startActivity(intent);
Receive data:
Bundle b = getIntent().getExtras();
int index = b.getInt("index");
If you use AsyncTask there is no need of any background thread inside onPostExecute(...). So, remove the thread inside onPostExecute(...) your problem will be solved if those values you are sending not null in onPostExecute(..).
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
Try this code for onPostExecute(String response) instead of yours
protected void onPostExecute(String response) {
// dismiss the dialog after getting all products
pDialog.dismiss();
/**
* Updating parsed Places into LISTVIEW
* */
if (placeDetails != null) {
String status = placeDetails.status;
// check place deatils status
// Check for all possible status
if (status.equals("OK")) {
if (placeDetails.result != null) {
String name = placeDetails.result.name;
String address = placeDetails.result.formatted_address;
String phone = placeDetails.result.formatted_phone_number;
String latitude = Double
.toString(placeDetails.result.geometry.location.lat);
String longitude = Double
.toString(placeDetails.result.geometry.location.lng);
Intent in = new Intent(getApplicationContext(), Email.class);
in.putExtra("nameValue", name);
in.putExtra("addValue", address);
in.putExtra("urlValue", phone);
startActivity(in);
Log.d("Place ", name + address + phone + latitude
+ longitude);
}
} else if (status.equals("ZERO_RESULTS")) {
alert.showAlertDialog(SinglePlaceActivity.this, "Near Places",
"Sorry no place found.", false);
} else if (status.equals("UNKNOWN_ERROR")) {
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry unknown error occured.", false);
} else if (status.equals("OVER_QUERY_LIMIT")) {
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry query limit to google places is reached", false);
} else if (status.equals("REQUEST_DENIED")) {
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured. Request is denied", false);
} else if (status.equals("INVALID_REQUEST")) {
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured. Invalid Request", false);
} else {
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured.", false);
}
} else {
alert.showAlertDialog(SinglePlaceActivity.this, "Places Error",
"Sorry error occured.", false);
}
}
I spent weeks on this problem. It seems that you should take note of what data type the value is stored as in the "sender" activity. As I have different activities which starts my "receiver" activity, I added this if statement to handle both data types (considering someId is a Long Data Type).
someId = getIntent().getLongExtra(EXTRA_ID,0);
if (someId < 1){
someId = Long.parseLong(getIntent().getStringExtra(EXTRA_ID));
}
Unfortunately I can not explain why, maybe some Guru can enlighten us common folk...
In my application I want to receive SMS and afert that, I want to get the the location of the phone and when I have the location, I want to send it By SMS...
by now, there is what I have :
package com.receiver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver{
private final String ACTION_RECEIVE_SMS = "android.provider.Telephony.SMS_RECEIVED";
private String numero;
private String msg;
#Override
public void onReceive(Context context, Intent intent){
Log.i("ReceiveBootCompleted","****** Boot terminer ********************");
Log.i("ReceiveBootCompleted"," ***** lancement du service Test **************");
context.startService(new Intent().setComponent(new ComponentName(context.getPackageName(), SMSReceiver.class.getName())));
if (intent.getAction().equals(ACTION_RECEIVE_SMS)){
Bundle bundle = intent.getExtras();
if (bundle != null){
Object[] pdus = (Object[]) bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++){
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
if (messages.length > -1){
final String messageBody = messages[0].getMessageBody();
final String phoneNumber = >messages[0].getDisplayOriginatingAddress();
if(messageBody.equals("mollo")){
app.smartfinder.SmartFinderActivity.send_message(phoneNumber);
}
}
}
}
}
and :
package app.smartfinder;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;
public class SmartFinderActivity extends Activity implements LocationListener {
LocationManager lm;
private Location location;
private double lat = 0;
private double lng = 0;
TextView position;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState){
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lm = (LocationManager) this.getSystemService(LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, this);
position = (TextView)findViewById(R.id.var_current_pos);
}
public void onClick_conf(View view){
Toast.makeText(SmartFinderActivity.this, "config", Toast.LENGTH_LONG).show();
Intent settingsActivity = new Intent(getBaseContext(), Preferences.class);
startActivity(settingsActivity);
}
public void onClick_hist (View view){
Toast.makeText(SmartFinderActivity.this, "history", Toast.LENGTH_LONG).show();
}
public void onLocationChanged(Location location) {
lat = location.getLatitude();
lng = location.getLongitude();
afficherAdresse();
position.setOnClickListener(new OnClickListener() { public void onClick(View v) {
Intent intent_map = new Intent(getBaseContext(), Map.class);
intent_map.putExtra("lat", lat);
intent_map.putExtra("lng", lng);
startActivity(intent_map);
}
});
lm.removeUpdates(this);
}
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
public void afficherAdresse() {
Geocoder geo = new Geocoder(SmartFinderActivity.this);
try {
List<Address> adresses = geo.getFromLocation(lat,lng,1);
if(adresses != null && adresses.size() == 1){
Address adresse = adresses.get(0);
//if geocoder find a adresse, we can use it
position.setText( adresse.getAddressLine(0) + " " + adresse.getPostalCode() + " " + adresse.getLocality());
}
else {
//else: no adress
position.setText("L'adresse n'a pu être déterminée");
}
} catch (IOException e) {
e.printStackTrace();
position.setText("L'adresse n'a pu être déterminée");
}
}
public static void send_message(String phoneNumber) {
// `refresh Location : that's the problem ! `
// send method : not difficult
}
}
My problem is that I want to refresh my position when method "send_message" is called.
thank you for your help
I think that you're asking how to get your current location when you receive an SMS message so that you can send back the current location in another SMS message. I think that you are assuming that your are able to just make a call to get your current location to report back.
GPS doesn't work that way. It needs to run for a little while to get enough messages from enough satellites to be able to determine a position and an accuracy for that position. So there is no single function call to simply get the device location instantly.
Instead it is necessary to run a background task (I use an Async Task) to listen to position updates and the iterate to the current location. My task turns off the listening (and the GPS hardware) when it has a good enough fix to save battery life.
See a previous related answer for more information.
It is possible to ask the Location Manager for the current position. However, this is the last position that it recorded. If no application has used the GPS hardware for a while then that postion fix could be very old and therefore not accurate at all. At work, my building shields the GPS signals (metal cladding) and so my phone currently believes that it is at my home many miles away which is where I last used a GPS enabled app.
As SMS takes a variable time to be delivered I think that it is probably correct to take a few extra seconds to fire off the GPS collection and wait for a good enough fix before responding. SMS is not an instant delivery vehicle so the extra few seconds delay in getting a good fix will not add much to the round-trip time of your SMS messages.