I'm trying to get user location in the background.
Everything works great on my phone (htc one m7), but from some reason it's not working on two devices I tested:
Samsung galaxy s3
Sony Xperia Z1
btw: I added everything to the manifest as it should be.
this is my code:
**BackgroundLocationService **
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationRequest;
public class BackgroundLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
IBinder mBinder = new LocalBinder();
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;
private Boolean servicesAvailable = false;
public class LocalBinder extends Binder {
public BackgroundLocationService getServerInstance() {
return BackgroundLocationService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
mInProgress = false;
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(0);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(1);
servicesAvailable = servicesConnected();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
public int onStartCommand (Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
return START_STICKY;
setUpLocationClientIfNeeded();
if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress)
{
mInProgress = true;
mLocationClient.connect();
}
return START_STICKY;
}
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
private void setUpLocationClientIfNeeded()
{
if(mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
}
// Define the callback method that receives location updates
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void appendLog(String text, String filename)
{
File logFile = new File(filename);
if (!logFile.exists())
{
try
{
logFile.createNewFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onDestroy(){
// Turn off the request flag
mInProgress = false;
if(servicesAvailable && mLocationClient != null) {
//mLocationClient.removeLocationUpdates(callbackIntent);
// Destroy the current location client
mLocationClient = null;
}
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle bundle) {
// Request location updates using static settings
Intent intent = new Intent(this, LocationReceiver.class);
PendingIntent locationIntent = PendingIntent.getBroadcast(getApplicationContext(), 14872, intent, PendingIntent.FLAG_CANCEL_CURRENT);
mLocationClient.requestLocationUpdates(mLocationRequest, locationIntent);
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mLocationClient = null;
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
/*
* 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()) {
// If no resolution is available, display an error dialog
} else {
}
}
}
**LocationReceiver **
import java.util.List;
import java.util.Locale;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.util.Log;
import com.google.android.gms.location.LocationClient;
public class LocationReceiver extends BroadcastReceiver {
public static double lat;
public static double alt;
public static String address;
#Override
public void onReceive(Context context, Intent intent) {
Location location = (Location) intent.getExtras().get(LocationClient.KEY_LOCATION_CHANGED);
Log.d("New Location Reciver", "location "+location.toString());
lat = location.getLatitude();
alt = location.getAltitude();
address = getAddressByCord(lat, alt, context);
}
public static String getAddressByCord(double lat, double longi, Context context) {
try {
Geocoder geo = new Geocoder(context, Locale.getDefault());
List<Address> addresses = geo.getFromLocation(lat, longi, 1);
if (addresses.isEmpty()) {
return "Waiting for Location";
} else {
if (addresses.size() > 0) {
String s = "";
if (addresses.get(0).getFeatureName() != null)
s += addresses.get(0).getFeatureName();
if (addresses.get(0).getThoroughfare() != null)
s += "," + addresses.get(0).getThoroughfare();
if (addresses.get(0).getLocality() != null)
s += "," + addresses.get(0).getLocality();
if (addresses.get(0).getAdminArea() != null)
s += "," + addresses.get(0).getAdminArea();
if (addresses.get(0).getCountryName() != null)
s += "," + addresses.get(0).getCountryName();
return s;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
if someone has any idea, Thank you!
code to check for google play services.
private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 94378;
private boolean isGooglePlay() {
int mIsGooglePlayServicesAvailable = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(context);
switch (mIsGooglePlayServicesAvailable) {
case ConnectionResult.SUCCESS:
return true;
default:
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
mIsGooglePlayServicesAvailable, this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment for the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
// Set the dialog in the DialogFragment
errorFragment.setDialog(errorDialog);
// Show the error dialog in the DialogFragment
errorFragment.show(getSupportFragmentManager(),
"Location Updates");
}
// case ConnectionResult.SERVICE_MISSING:
// case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
// case ConnectionResult.SERVICE_DISABLED:
// case ConnectionResult.SERVICE_INVALID:
// case ConnectionResult.DATE_INVALID:
}
return false;
}
/*
* This is a class used to resolve errors with google play services It is
* copied code that doesn't run durring normal operation.
*/
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;
}
}
I found the answer.
It was the devices own definitions.
The device was not enabling apps to use location .
thank you anyway!
Related
I would like to write applications for android, which is designed to send data from sensors such as accelerometer, gyroscope, etc.
via bluetooth to another device.
I download from github Bluetooth Chat on Android and wrote a class that gets data from the accelerometer, but I can not connect it.
Here is a the link to github I downloaded:
https://github.com/googlesamples/android-BluetoothChat
Here is the class from this github which I tried to change:
import android.app.ActionBar;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.content.Context.*;
import com.example.android.common.logger.Log;
/**
* This fragment controls Bluetooth to communicate with other devices.
*/
public class BluetoothChatFragment extends Fragment{
private static final String TAG = "BluetoothChatFragment";
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;
// Layout Views
private ListView mConversationView;
private EditText mOutEditText;
private Button mSendButton;
private Sensor mySensor;
private SensorManager SM;
private float x, y, z;
private SensorEvent event;
/**
* Name of the connected device
*/
private String mConnectedDeviceName = null;
/**
* Array adapter for the conversation thread
*/
private ArrayAdapter<String> mConversationArrayAdapter;
/**
* String buffer for outgoing messages
*/
private StringBuffer mOutStringBuffer;
/**
* Local Bluetooth adapter
*/
private BluetoothAdapter mBluetoothAdapter = 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
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
FragmentActivity activity = getActivity();
Toast.makeText(activity, "Bluetooth is not available", Toast.LENGTH_LONG).show();
activity.finish();
}
}
#Override
public void onStart() {
super.onStart();
// If BT is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (!mBluetoothAdapter.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();
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_bluetooth_chat, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
mConversationView = (ListView) view.findViewById(R.id.in);
mOutEditText = (EditText) view.findViewById(R.id.edit_text_out);
mSendButton = (Button) view.findViewById(R.id.button_send);
}
/**
* Set up the UI and background operations for chat.
*/
private void setupChat() {
Log.d(TAG, "setupChat()");
// Initialize the array adapter for the conversation thread
mConversationArrayAdapter = new ArrayAdapter<String>(getActivity(), R.layout.message);
mConversationView.setAdapter(mConversationArrayAdapter);
// Initialize the compose field with a listener for the return key
mOutEditText.setOnEditorActionListener(mWriteListener);
// Initialize the send button with a listener that for click events
mSendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Send a message using content of the edit text widget
View view = getView();
// if (null != view) {
TextView textView = (TextView) view.findViewById(R.id.edit_text_out);
String message = textView.getText().toString();
sendMessage(message);
// }
}
});
// Initialize the BluetoothChatService to perform bluetooth connections
mChatService = new BluetoothChatService(getActivity(), mHandler);
// Initialize the buffer for outgoing messages
mOutStringBuffer = new StringBuffer("");
}
/**
* Makes this device discoverable for 300 seconds (5 minutes).
*/
private void ensureDiscoverable() {
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
/**
* Sends a message.
*
* #param message A string of text to send.
*/
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() >= 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
/**
* The action listener for the EditText widget, to listen for the return key
*/
private TextView.OnEditorActionListener mWriteListener
= new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
// If the action is a key-up event on the return key, send the message
if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
String message = view.getText().toString();
sendMessage(message);
}
return true;
}
};
/**
* Updates the status on the action bar.
*
* #param resId a string resource ID
*/
private void setStatus(int resId) {
FragmentActivity activity = getActivity();
if (null == activity) {
return;
}
final ActionBar actionBar = activity.getActionBar();
if (null == actionBar) {
return;
}
actionBar.setSubtitle(resId);
}
/**
* Updates the status on the action bar.
*
* #param subTitle status
*/
private void setStatus(CharSequence subTitle) {
FragmentActivity activity = getActivity();
if (null == activity) {
return;
}
final ActionBar actionBar = activity.getActionBar();
if (null == actionBar) {
return;
}
actionBar.setSubtitle(subTitle);
}
/**
* The Handler that gets information back from the BluetoothChatService
*/
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:
setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
mConversationArrayAdapter.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
setStatus(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
setStatus(R.string.title_not_connected);
break;
}
break;
case Constants.MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
mConversationArrayAdapter.add("Me: " );
break;
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);
mConversationArrayAdapter.add(mConnectedDeviceName + ": " + readMessage);
break;
case Constants.MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
if (null != activity) {
Toast.makeText(activity, "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
}
break;
case Constants.MESSAGE_TOAST:
if (null != activity) {
Toast.makeText(activity, msg.getData().getString(Constants.TOAST),
Toast.LENGTH_SHORT).show();
}
break;
}
}
};
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectDevice(data, true);
}
break;
case REQUEST_CONNECT_DEVICE_INSECURE:
// When DeviceListActivity 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 {
// User did not enable Bluetooth or an error occurred
Log.d(TAG, "BT not enabled");
Toast.makeText(getActivity(), R.string.bt_not_enabled_leaving,
Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
}
/**
* Establish connection with other device
*
* #param data An {#link Intent} with {#link DeviceListActivity#EXTRA_DEVICE_ADDRESS} extra.
* #param secure Socket Security type - Secure (true) , Insecure (false)
*/
private void connectDevice(Intent data, boolean secure) {
// Get the device MAC address
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mChatService.connect(device, secure);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.bluetooth_chat, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.secure_connect_scan: {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
}
case R.id.insecure_connect_scan: {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
return true;
}
case R.id.discoverable: {
// Ensure this device is discoverable by others
ensureDiscoverable();
return true;
}
}
return false;
}
public void setX(float x)
{
this.x = x;
}
public void setY(float y)
{
this.y = y;
}
public void setZ(float z)
{
this.z = z;
}
}
And here is Accelerometer Class:
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
public class AkcelerometrActivity extends AppCompatActivity implements SensorEventListener {
private Sensor mySensor;
private SensorManager SM;
private float x, y, z;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_akcelerometr);
SM = (SensorManager)getSystemService(SENSOR_SERVICE);
mySensor = SM.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
SM.registerListener(this, mySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
public void onSensorChanged(SensorEvent event)
{
x = event.values[0];
y = event.values[1];
z = event.values[2];
}
public float getX()
{
return x;
}
public float getY()
{
return y;
}
public float getZ()
{
return z;
}
}
Any ideas?
Thank you in advance.
I have a MediaRecorder in my IntentService class.
I want to
Run an IntentService to start recording audio
Run an IntentService to stop recording audio
I use IntentService because I want the audio recording to run even when my phone screen is turned off. Service runs in the background, so this is a good approach, right?
Anyways, I initiate my MediaRecorder in my IntentService at Step #1.
At Step#2, my instantiated MediaRecorder is NULL. It seems that all variable values inside the IntentService are reset, because the service ends and calls onDestroy.
What should I do? How do I keep a reference to my MediaRecorder ?
Update: Pasting my IntentService class
package com.dan190.enregistreur.BackgroundService;
import android.app.IntentService;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import com.dan190.enregistreur.RecordedFilesActivity;
import com.dan190.enregistreur.Util.RecordingStatus;
import java.io.IOException;
import java.util.Calendar;
/**
* Created by Dan on 17/03/2017.
*/
public class RecorderService extends IntentService {
private static final String TAG = RecorderService.class.getName();
private MediaRecorder mMediaRecorder;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* #param name Used to name the worker thread, important only for debugging.
*/
public RecorderService(String name) {
super(name);
}
public RecorderService() {
super("RecorderService");
}
/**
* Handles intent.
* Unwraps intent to find out if we need to start, pause, or stop
* #param intent
*/
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Log.d(TAG, "onHandleIntent");
Bundle bundle = intent.getExtras();
int status = bundle.getInt(RecordingStatus.RECORDING_STATUS_KEY);
switch (status) {
case RecordingStatus.STANDBY:
//do nothing
break;
case RecordingStatus.RECORDING:
//if mediaPlayer is null, initiate
//set datasource
//prepare
//record
Log.d(TAG, "start recording");
startRecording();
break;
case RecordingStatus.PAUSED:
//pause
Log.d(TAG, "pause recording");
break;
case RecordingStatus.STOPPED:
//stop
Log.d(TAG, "stop recording");
stopRecording();
Intent newIntent = new Intent(this, RecordedFilesActivity.class);
startActivity(newIntent);
break;
case RecordingStatus.OPENDIR:
//open recorded files
Log.d(TAG, "open directory");
getFileName();
Intent newIntent2 = new Intent(this, RecordedFilesActivity.class);
startActivity(newIntent2);
break;
default:
break;
}
}
/**
* File stuff
*/
private static String pathName,
fileName;
public static String getPath() {
return pathName;
}
public static String getFilePath() {
return fileName;
}
private String getFileName() {
Calendar calendar = Calendar.getInstance();
PackageManager m = getPackageManager();
pathName = getPackageName();
PackageInfo p = null;
try {
p = m.getPackageInfo(pathName, 0);
} catch(PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
pathName = p.applicationInfo.dataDir;
// fileName = Environment.getExternalStorageDirectory() + "/" + Environment.DIRECTORY_DCIM + "/Recordings";
fileName = pathName;
fileName += String.format("/%d_%d_%d_%d_%d_%d.3gp", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY) + 1, calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
return fileName;
}
/**
* Recorder stuff
*/
private void startRecording() {
String fileName = getFileName();
Log.d(TAG, String.format("file name is %s", fileName));
if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder();
//NOTE that mediaRecorder cannot pause for API < 24, which is Android 7.0
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(getFileName());
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mMediaRecorder.prepare();
} catch(IOException e) {
Log.e(TAG, "prepare() failed");
e.printStackTrace();
}
try {
mMediaRecorder.start();
} catch(IllegalStateException e) {
Log.e(TAG, e.getStackTrace().toString());
}
}
private void stopRecording() {
try {
mMediaRecorder.stop();
mMediaRecorder.reset();
} catch(RuntimeException e) {
e.printStackTrace();
}
releaseMediaRecorder();
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder = null;
} else {
Log.w(TAG, "mediaRecroder is already Null");
}
}
/**
* Lifecycle stuff
*/
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
}
Fixed it by using Service instead of Intent service.
This post proved helpful. Service.onDestroy() is called directly after creation, anyway the Service does its work
Basically, IntentService is designed so that it will immediately stop all services after the code within onHandleIntent is finished. Thus, I was never able to keep my MediaRecorder alive.
With a normal Service, I am able to have more control over the lifecycle of my service. I can start and stop it when I want to. With IntentService, this is not possible.
I am trying to send the selected image the user selected from their Google Drive to another function. I would like retrieve the content the user selected and send the photo uri or a bitmap of that photo to a function. Can anyone help me out?
This is my code:
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveFolder;
import com.google.android.gms.drive.DriveId;
import com.google.android.gms.drive.MetadataChangeSet;
import com.google.android.gms.drive.OpenFileActivityBuilder;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "Google Drive Activity";
private static final int REQUEST_CODE_RESOLUTION = 1;
private static final int REQUEST_CODE_OPENER = 2;
private GoogleApiClient mGoogleApiClient;
private boolean fileOperation = false;
private DriveId mFileId;
public DriveFile file;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "Inside the onCreate Method");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* Called when the activity will start interacting with the user.
* At this point your activity is at the top of the activity stack,
* with user input going to it.
*/
#Override
protected void onResume() {
super.onResume();
Log.i(TAG, "Inside the onResume method");
if (mGoogleApiClient == null) {
/**
* Create the API client and bind it to an instance variable.
* We use this instance as the callback for connection and connection failures.
* Since no account name is passed, the user is prompted to choose.
*/
Log.i(TAG, "Creating the API client");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
Log.i(TAG,"About to call connect method().");
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
Log.i(TAG,"inside the onStop method");
if (mGoogleApiClient != null) {
// disconnect Google API client connection
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Inside onConnectionFailed()");
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
/**
* The failure has a resolution. Resolve it.
* Called typically when the app is not yet authorized, and an authorization
* dialog is displayed to the user.
*/
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
/**
* It invoked when Google API client connected
* #param connectionHint
*/
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Inside onConnected Method()");
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_LONG).show();
}
/**
* It invoked when connection suspend
* #param cause
*/
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
public void onClickCreateFile(View view){
fileOperation = true;
// create new contents resource
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(driveContentsCallback);
}
public void onClickOpenFile(View view){
fileOperation = false;
Log.i(TAG, "Selected the onClickOpenFile button");
// create new contents resource
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(driveContentsCallback);
}
/**
* Open list of folder and file of the Google Drive
*/
public void OpenFileFromGoogleDrive(){
Log.i(TAG, "Inside OpenFIleFromGoogleDrive method.");
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
//Restricting the user to only select txt and image support files for Tesseract.
.setMimeType(new String[] { "text/plain", "image/png", "image/jpeg", "image/bmp", "jpg" })
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.w(TAG, "Unable to send intent", e);
}
}
/**
* This is Result result handler of Drive contents.
* this callback method call CreateFileOnGoogleDrive() method
* and also call OpenFileFromGoogleDrive() method,
* send intent onActivityResult() method to handle result.
*/
final ResultCallback<DriveApi.DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult result) {
Log.i(TAG, "Inside onResultCallback()");
if (result.getStatus().isSuccess()) {
if (fileOperation == true) {
CreateFileOnGoogleDrive(result);
} else {
OpenFileFromGoogleDrive();
}
}
}
};
/**
* Create a file in root folder using MetadataChangeSet object.
* #param result
*/
public void CreateFileOnGoogleDrive(DriveApi.DriveContentsResult result){
Log.i(TAG, "Inside createfileongoogledrive method");
final DriveContents driveContents = result.getDriveContents();
// Perform I/O off the UI thread.
new Thread() {
#Override
public void run() {
// write content to DriveContents
OutputStream outputStream = driveContents.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
try {
writer.write("Hello Joseph, you created me(: !");
writer.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("test2")
.setMimeType("text/plain")
.setStarred(true).build();
// create a file in root folder
Drive.DriveApi.getRootFolder(mGoogleApiClient)
.createFile(mGoogleApiClient, changeSet, driveContents)
.setResultCallback(fileCallback);
}
}.start();
}
/**
* Handle result of Created file
*/
final private ResultCallback<DriveFolder.DriveFileResult> fileCallback = new
ResultCallback<DriveFolder.DriveFileResult>() {
#Override
public void onResult(DriveFolder.DriveFileResult result) {
if (result.getStatus().isSuccess()) {
Toast.makeText(getApplicationContext(), "file created: "+""+
result.getDriveFile().getDriveId(), Toast.LENGTH_LONG).show();
}
return;
}
};
/**
* Handle Response of selected file
* #param requestCode
* #param resultCode
* #param data
*/
#Override
protected void onActivityResult(final int requestCode,
final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_OPENER:
if (resultCode == RESULT_OK) {
mFileId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
Log.e("file id", mFileId.getResourceId() + "");
String url = "https://drive.google.com/open?id="+ mFileId.getResourceId();
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
}
I followed this and this links to get current location. Here without using Wi-fi and GPS getting current location but it is not updating when location changed, if I on GPS/Wi-fi it starting updating. Here I want to get updates with based on only cell tower with low battery consumption and high accuracy.
This is my code
MainActivity.java
package com.example.offline;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import android.content.IntentSender;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MainActivity extends FragmentActivity implements
LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
// A request to connect to Location Services
private LocationRequest mLocationRequest;
// Stores the current instantiation of the location client in this object
private LocationClient mLocationClient;
// Handles to UI widgets
private TextView mLatLng;
private TextView mAddress;
private ProgressBar mActivityIndicator;
private TextView mConnectionState;
private TextView mConnectionStatus;
// Handle to SharedPreferences for this app
SharedPreferences mPrefs;
// Handle to a SharedPreferences editor
SharedPreferences.Editor mEditor;
boolean mUpdatesRequested = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get handles to the UI view objects
mLatLng = (TextView) findViewById(R.id.lat_lng);
mAddress = (TextView) findViewById(R.id.address);
// mActivityIndicator = (ProgressBar) findViewById(R.id.address_progress);
mConnectionState = (TextView) findViewById(R.id.text_connection_state);
mConnectionStatus = (TextView) findViewById(R.id.text_connection_status);
// Create a new global location parameters object
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
// Note that location updates are off until the user turns them on
mUpdatesRequested = false;
// Open Shared Preferences
mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE);
// Get an editor
mEditor = mPrefs.edit();
mLocationClient = new LocationClient(this, this, this);
}
#Override
public void onStop() {
// If the client is connected
if (mLocationClient.isConnected()) {
stopPeriodicUpdates();
}
// After disconnect() is called, the client is considered "dead".
mLocationClient.disconnect();
super.onStop();
}
#Override
public void onPause() {
// Save the current setting for updates
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, mUpdatesRequested);
mEditor.commit();
super.onPause();
}
#Override
public void onStart() {
super.onStart();
/*
* Connect the client. Don't re-start any requests here;
* instead, wait for onResume()
*/
mLocationClient.connect();
}
#Override
public void onResume() {
super.onResume();
// If the app already has a setting for getting location updates, get it
if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
mUpdatesRequested = mPrefs.getBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
// Otherwise, turn off location updates until requested
} else {
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
mEditor.commit();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
// Choose what to do based on the request code
switch (requestCode) {
// If the request code matches the code sent in onConnectionFailed
case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST :
switch (resultCode) {
// If Google Play services resolved the problem
case Activity.RESULT_OK:
// Log the result
Log.d(LocationUtils.APPTAG, getString(R.string.resolved));
// Display the result
mConnectionState.setText(R.string.connected);
mConnectionStatus.setText(R.string.resolved);
break;
// If any other result was returned by Google Play services
default:
// Log the result
Log.d(LocationUtils.APPTAG, getString(R.string.no_resolution));
// Display the result
mConnectionState.setText(R.string.disconnected);
mConnectionStatus.setText(R.string.no_resolution);
break;
}
// If any other request code was received
default:
// Report that this Activity received an unknown requestCode
Log.d(LocationUtils.APPTAG,
getString(R.string.unknown_activity_request_code, requestCode));
break;
}
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available));
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0);
if (dialog != null) {
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(dialog);
errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
}
return false;
}
}
public void getLocation(View v) {
// If Google Play Services is available
if (servicesConnected()) {
// Get the current location
Location currentLocation = mLocationClient.getLastLocation();
// Display the current location in the UI
mLatLng.setText(LocationUtils.getLatLng(this, currentLocation));
}
}
// For Eclipse with ADT, suppress warnings about Geocoder.isPresent()
#SuppressLint("NewApi")
public void getAddress(View v) {
// In Gingerbread and later, use Geocoder.isPresent() to see if a geocoder is available.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) {
// No geocoder is present. Issue an error message
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
if (servicesConnected()) {
// Get the current location
Location currentLocation = mLocationClient.getLastLocation();
// Turn the indefinite activity indicator on
mActivityIndicator.setVisibility(View.VISIBLE);
// Start the background task
(new MainActivity.GetAddressTask(this)).execute(currentLocation);
}
}
public void startUpdates(View v) {
mUpdatesRequested = true;
if (servicesConnected()) {
startPeriodicUpdates();
}
}
public void stopUpdates(View v) {
mUpdatesRequested = false;
if (servicesConnected()) {
stopPeriodicUpdates();
}
}
#Override
public void onConnected(Bundle bundle) {
mConnectionStatus.setText(R.string.connected);
if (mUpdatesRequested) {
startPeriodicUpdates();
}
}
#Override
public void onDisconnected() {
mConnectionStatus.setText(R.string.disconnected);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(
this,
LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
// If no resolution is available, display a dialog to the user with the error.
showErrorDialog(connectionResult.getErrorCode());
}
}
#Override
public void onLocationChanged(Location location) {
// Report to the UI that the location was updated
mConnectionStatus.setText(R.string.location_updated);
// In the UI, set the latitude and longitude to the value received
mLatLng.setText(LocationUtils.getLatLng(this, location));
}
private void startPeriodicUpdates() {
mLocationClient.requestLocationUpdates(mLocationRequest, this);
mConnectionState.setText(R.string.location_requested);
}
private void stopPeriodicUpdates() {
mLocationClient.removeLocationUpdates(this);
mConnectionState.setText(R.string.location_updates_stopped);
}
protected class GetAddressTask extends AsyncTask<Location, Void, String> {
// Store the context passed to the AsyncTask when the system instantiates it.
Context localContext;
// Constructor called by the system to instantiate the task
public GetAddressTask(Context context) {
// Required by the semantics of AsyncTask
super();
// Set a Context for the background task
localContext = context;
}
#Override
protected String doInBackground(Location... params) {
Geocoder geocoder = new Geocoder(localContext, Locale.getDefault());
// Get the current location from the input parameter list
Location location = params[0];
// Create a list to contain the result address
List <Address> addresses = null;
// Try to get an address for the current location. Catch IO or network problems.
try {
addresses = geocoder.getFromLocation(location.getLatitude(),
location.getLongitude(), 1
);
// Catch network or other I/O problems.
} catch (IOException exception1) {
// Log an error and return an error message
Log.e(LocationUtils.APPTAG, getString(R.string.IO_Exception_getFromLocation));
// print the stack trace
exception1.printStackTrace();
// Return an error message
return (getString(R.string.IO_Exception_getFromLocation));
// Catch incorrect latitude or longitude values
} catch (IllegalArgumentException exception2) {
// Construct a message containing the invalid arguments
String errorString = getString(
R.string.illegal_argument_exception,
location.getLatitude(),
location.getLongitude()
);
// Log the error and print the stack trace
Log.e(LocationUtils.APPTAG, errorString);
exception2.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
String addressText = getString(R.string.address_output_string,
// 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;
// If there aren't any addresses, post a message
} else {
return getString(R.string.no_address_found);
}
}
#Override
protected void onPostExecute(String address) {
// Turn off the progress bar
mActivityIndicator.setVisibility(View.GONE);
// Set the address in the UI
mAddress.setText(address);
}
}
private void showErrorDialog(int errorCode) {
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
errorCode,
this,
LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment in which to show the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
// Set the dialog in the DialogFragment
errorFragment.setDialog(errorDialog);
// Show the error dialog in the DialogFragment
errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
}
}
ublic 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;
}
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
/*
* This method must return a Dialog to the DialogFragment.
*/
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
}
LocationUtils.java
package com.example.offline;
import android.content.Context;
import android.location.Location;
/**
* Defines app-wide constants and utilities
*/
public final class LocationUtils {
// Debugging tag for the application
public static final String APPTAG = "LocationSample";
// Name of shared preferences repository that stores persistent state
public static final String SHARED_PREFERENCES =
"com.example.android.location.SHARED_PREFERENCES";
// Key for storing the "updates requested" flag in shared preferences
public static final String KEY_UPDATES_REQUESTED =
"com.example.android.location.KEY_UPDATES_REQUESTED";
/*
* Define a request code to send to Google Play services
* This code is returned in Activity.onActivityResult
*/
public final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
/*
* Constants for location update parameters
*/
// Milliseconds per second
public static final int MILLISECONDS_PER_SECOND = 1000;
// The update interval
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
// A fast interval ceiling
public static final int FAST_CEILING_IN_SECONDS = 1;
// Update interval in milliseconds
public static final long UPDATE_INTERVAL_IN_MILLISECONDS =
MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// A fast ceiling of update intervals, used when the app is visible
public static final long FAST_INTERVAL_CEILING_IN_MILLISECONDS =
MILLISECONDS_PER_SECOND * FAST_CEILING_IN_SECONDS;
// Create an empty string for initializing strings
public static final String EMPTY_STRING = new String();
/**
* Get the latitude and longitude from the Location object returned by
* Location Services.
*
* #param currentLocation A Location object containing the current location
* #return The latitude and longitude of the current location, or null if no
* location is available.
*/
public static String getLatLng(Context context, Location currentLocation) {
// If the location is valid
if (currentLocation != null) {
// Return the latitude and longitude as strings
return context.getString(
R.string.latitude_longitude,
currentLocation.getLatitude(),
currentLocation.getLongitude());
} else {
// Otherwise, return the empty string
return EMPTY_STRING;
}
}
}
LocationServiceErrorMessages.java
package com.example.offline;
import com.google.android.gms.common.ConnectionResult;
import android.content.Context;
import android.content.res.Resources;
/**
* Map error codes to error messages.
*/
public class LocationServiceErrorMessages {
// Don't allow instantiation
private LocationServiceErrorMessages() {}
public static String getErrorString(Context context, int errorCode) {
// Get a handle to resources, to allow the method to retrieve messages.
Resources mResources = context.getResources();
// Define a string to contain the error message
String errorString;
// Decide which error message to get, based on the error code.
switch (errorCode) {
case ConnectionResult.DEVELOPER_ERROR:
errorString = mResources.getString(R.string.connection_error_misconfigured);
break;
case ConnectionResult.INTERNAL_ERROR:
errorString = mResources.getString(R.string.connection_error_internal);
break;
case ConnectionResult.INVALID_ACCOUNT:
errorString = mResources.getString(R.string.connection_error_invalid_account);
break;
case ConnectionResult.LICENSE_CHECK_FAILED:
errorString = mResources.getString(R.string.connection_error_license_check_failed);
break;
case ConnectionResult.NETWORK_ERROR:
errorString = mResources.getString(R.string.connection_error_network);
break;
case ConnectionResult.RESOLUTION_REQUIRED:
errorString = mResources.getString(R.string.connection_error_needs_resolution);
break;
case ConnectionResult.SERVICE_DISABLED:
errorString = mResources.getString(R.string.connection_error_disabled);
break;
case ConnectionResult.SERVICE_INVALID:
errorString = mResources.getString(R.string.connection_error_invalid);
break;
case ConnectionResult.SERVICE_MISSING:
errorString = mResources.getString(R.string.connection_error_missing);
break;
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
errorString = mResources.getString(R.string.connection_error_outdated);
break;
case ConnectionResult.SIGN_IN_REQUIRED:
errorString = mResources.getString(
R.string.connection_error_sign_in_required);
break;
default:
errorString = mResources.getString(R.string.connection_error_unknown);
break;
}
// Return the error message
return errorString;
}
}
I am getting the following exception when I run the texter application in android.
STACK_TRACE :
java.lang.NullPointerException at
com.texter.messenger.SmsReceiverService$ServiceHandler.handleMessage(SmsReceiverService.java:116)
at android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:123) at
android.os.HandlerThread.run(HandlerThread.java:60) , PHONE_MODEL :
GT-I9000 , ANDROID_VERSION : 2.2 , APP_VERSION_CODE : 10
30.Nov.2011 00:33:50 AM , CUSTOM_DATA : , STACK_TRACE : java.lang.IllegalArgumentException: Receiver not registered:
android.widget.ViewFlipper$1#40597cc0 at
android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:634) at
android.app.ContextImpl.unregisterReceiver(ContextImpl.java:881) at
android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:331)
at
android.widget.ViewFlipper.onDetachedFromWindow(ViewFlipper.java:104)
at android.view.View.dispatchDetachedFromWindow(View.java:6235) at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1250)
at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
at
android.view.ViewRoot.dispatchDetachedFromWindow(ViewRoot.java:1838)
at android.view.ViewRoot.doDie(ViewRoot.java:2916) at
android.view.ViewRoot.die(ViewRoot.java:2886) at
android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:254)
at
android.view.Window$LocalWindowManager.removeViewImmediate(Window.java:445)
at
android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3182)
at
android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3287)
at android.app.ActivityThread.access$1600(ActivityThread.java:132)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1042)
at android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:150) at
android.app.ActivityThread.main(ActivityThread.java:4293) at
java.lang.reflect.Method.invokeNative(Native Method) at
java.lang.reflect.Method.invoke(Method.java:507) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at
dalvik.system.NativeStart.main(Native Method).
I am new to these errors. How to solve these errors.
package com.texter.messenger;
import java.util.List;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.SmsMessage.MessageClass;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.texter.common.TexterConstants;
import com.texter.common.TexterNotification;
import com.texter.common.Utils;
import com.texter.data.TexterDB;
import com.texter.data.TexterDB.Schedule;
import com.texter.preferences.TexterPreferenceManager;
import com.texterpro.app.ConversationList;
import com.texterpro.app.R;
import com.texterpro.app.SmsPopupView;
public class SmsReceiverService extends Service {
private static final String LOG_TAG = TexterConstants.COMMON_TAG;
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
private static final String ACTION_MESSAGE_RECEIVED = "net.everythingandroid.smspopup.MESSAGE_RECEIVED";
private static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message";
// https://android.googlesource.com/platform/packages/apps/Mms/+/master/src/com/android/mms/transaction/SmsReceiverService.java
public static final String MESSAGE_SENT_ACTION = "com.android.mms.transaction.MESSAGE_SENT";
/*
* This is the number of retries and pause between retries that we will keep
* checking the system message database for the latest incoming message
*/
private static final int MESSAGE_RETRY = 8;
private static final int MESSAGE_RETRY_PAUSE = 1000;
private Context context;
private ServiceHandler mServiceHandler;
private Looper mServiceLooper;
private int mResultCode;
private static final Object mStartingServiceSync = new Object();
private static PowerManager.WakeLock mStartingService;
private static final int TOAST_HANDLER_MESSAGE_SENT = 0;
private static final int TOAST_HANDLER_MESSAGE_SEND_LATER = 1;
private static final int TOAST_HANDLER_MESSAGE_FAILED = 2;
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("Log.LOGTAG",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
context = getApplicationContext();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
Log.v(LOG_TAG, "Oncreate");
}
#Override
public void onStart(Intent intent, int startId) {
Log.v(LOG_TAG, "OnStart");
mResultCode = intent != null ? intent.getIntExtra("result", 0) : 0;
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
#Override
public void onDestroy() {
mServiceLooper.quit();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
Log.v(LOG_TAG, "handlemessage:");
Log.v(LOG_TAG, msg.toString());
int serviceId = msg.arg1;
Intent intent = (Intent) msg.obj;
String action = intent.getAction();
String dataType = intent.getType();
if (ACTION_SMS_RECEIVED.equals(action)) {
handleSmsReceived(intent);
} else if (ACTION_MMS_RECEIVED.equals(action)
&& MMS_DATA_TYPE.equals(dataType)) {
handleMmsReceived(intent);
} else if (MESSAGE_SENT_ACTION.equals(action)) {
handleSmsSent(intent);
} else if (ACTION_MESSAGE_RECEIVED.equals(action)) {
handleMessageReceived(intent);
}
// NOTE: We MUST not call stopSelf() directly, since we need to
// make sure the wake lock acquired by AlertReceiver is released.
finishStartingService(SmsReceiverService.this, serviceId);
}
}
/**
* Handle receiving a SMS message
*/
private void handleSmsReceived(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
SmsMessage[] messages = Utils.getMessagesFromIntent(intent);
if (messages != null) {
notifyMessageReceived(new SmsMmsMessage(context, messages,
System.currentTimeMillis()));
}
}
}
private void notifyMessageReceived(SmsMmsMessage message) {
// Class 0 SMS, let the system handle this
if (message.getMessageType() == SmsMmsMessage.MESSAGE_TYPE_SMS
&& message.getMessageClass() == MessageClass.CLASS_0) {
return;
}
TelephonyManager mTM = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
boolean callStateIdle = mTM.getCallState() == TelephonyManager.CALL_STATE_IDLE;
/*
* If popup is enabled for this user -AND- the user is not in a call
* -AND- -AND- phone is not docked -AND- (screen is locked -OR- (setting
* is OFF to only show on keyguard -AND- user is not in messaging app:
* then show the popup activity, otherwise check if notifications are on
* and just use the standard notification))
*/
boolean isApp = TexterPreferenceManager.getInstance(this)
.isAppEnabled();
boolean showPop = TexterPreferenceManager.getInstance(this)
.isPopupEnabled();
boolean showNotify = TexterPreferenceManager.getInstance(this)
.isNotifyEnabled();
// Log.v(LOG_TAG," App = "+ isApp );
// Log.v(LOG_TAG," pop = "+showPop );
// Log.v(LOG_TAG," notify = "+showNotify );
// if conversationList is visible then do not show pop
if (!ConversationList.isVisible()) {
if (isApp && callStateIdle && showPop) {
// Log.v(LOG_TAG," showing popup = " );
if (!SmsPopupView.isPopupVisible())
context.startActivity(message.getPopupIntent());
}
}
if (isApp && showNotify) {
TexterNotification.ShowMessageNotification(this, message);
}
}
/**
* Handle receiving a MMS message
*/
private void handleMmsReceived(Intent intent) {
}
/**
* Handle receiving an arbitrary message (potentially coming from a 3rd
* party app)
*/
private void handleMessageReceived(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
}
}
/*
* Handler to deal with showing Toast messages for message sent status
*/
public Handler mToastHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg != null) {
switch (msg.what) {
case TOAST_HANDLER_MESSAGE_SENT:
// TexterNotification.showToast(SmsReceiverService.this,R.string.quickreply_sent_toast);
break;
case TOAST_HANDLER_MESSAGE_SEND_LATER:
TexterNotification.showToast(SmsReceiverService.this,
R.string.quickreply_failed_send_later);
break;
case TOAST_HANDLER_MESSAGE_FAILED:
TexterNotification.showToast(SmsReceiverService.this,
R.string.quickreply_failed);
break;
}
}
}
};
/*
* Handle the result of a sms being sent
*/
private void handleSmsSent(Intent intent) {
Log.v(LOG_TAG, "HandleSMSSent called");
PackageManager pm = getPackageManager();
Intent sysIntent = null;
Intent tempIntent;
List<ResolveInfo> receiverList;
boolean forwardToSystemApp = true;
// Search for system messaging app that will receive our
// "message sent complete" type intent
tempIntent = intent.setClassName(
SmsMessageSender.MESSAGING_PACKAGE_NAME,
SmsMessageSender.MESSAGING_RECEIVER_CLASS_NAME);
tempIntent.setAction(SmsReceiverService.MESSAGE_SENT_ACTION);
receiverList = pm.queryBroadcastReceivers(tempIntent, 0);
if (receiverList.size() > 0) {
sysIntent = tempIntent;
}
Bundle b = intent.getExtras();
long rowid = 0;
rowid = b == null ? 0 : b.getLong("ROWID");
/*
* No system messaging app was found to forward this intent to,
* therefore we will need to do the final piece of this ourselves which
* is basically moving the message to the correct folder depending on
* the result.
*/
// TexterNotification.showToast(SmsReceiverService.this,
// "before moving folder");
if (sysIntent == null) {
forwardToSystemApp = false;
Uri uri = intent.getData();
Log.v(LOG_TAG, "id = " + rowid);
if (mResultCode == Activity.RESULT_OK) {
SmsMessageSender.moveMessageToFolder(this, uri,
SmsMessageSender.MESSAGE_TYPE_SENT);
} else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF)
|| (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {
SmsMessageSender.moveMessageToFolder(this, uri,
SmsMessageSender.MESSAGE_TYPE_QUEUED);
} else {
SmsMessageSender.moveMessageToFolder(this, uri,
SmsMessageSender.MESSAGE_TYPE_FAILED);
}
}
// Check the result and notify the user using a toast
if (mResultCode == Activity.RESULT_OK) {
mToastHandler.sendEmptyMessage(TOAST_HANDLER_MESSAGE_SENT);
TexterDB.getInstance().updateStatus(rowid,
Schedule.STATUS_SCHEDULED_SENT, 0);
} else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF)
|| (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {
TexterDB.getInstance().updateStatus(rowid,
Schedule.STATUS_NOT_SENT, -1);
} else {
mToastHandler.sendEmptyMessage(TOAST_HANDLER_MESSAGE_FAILED);
TexterDB.getInstance().updateStatus(rowid,
Schedule.STATUS_NOT_SENT, mResultCode);
}
if (forwardToSystemApp) {
try {
PendingIntent.getBroadcast(this, 0, sysIntent, 0).send(
mResultCode);
} catch (CanceledException e) {
e.printStackTrace();
}
}
}
/**
* Start the service to process the current event notifications, acquiring
* the wake lock before returning to ensure that the service will run.
*/
public static void beginStartingService(Context context, Intent intent) {
synchronized (mStartingServiceSync) {
if (mStartingService == null) {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
mStartingService = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"Texter.SmsReceiverService");
mStartingService.setReferenceCounted(false);
}
mStartingService.acquire();
context.startService(intent);
Log.v(LOG_TAG, "service started");
}
}
/**
* Called back by the service when it has finished processing notifications,
* releasing the wake lock if the service is now stopping.
*/
public static void finishStartingService(Service service, int startId) {
synchronized (mStartingServiceSync) {
if (mStartingService != null) {
if (service.stopSelfResult(startId)) {
mStartingService.release();
}
}
}
}
}
Look at the top of the trace... look at the code at:
com.texter.messenger.SmsReceiverService$ServiceHandler.handleMessage(SmsReceiverService.java:116)
Looking at the code... check that the variable intent is not null before you call handleSmsReceived
I had the same bug, still looking for the correct solution but temporarily I just comment out the onDetachFromWindow() method. In my case it was for testing purpose so commenting it out didn't affect me but not sure what's in your case but give it a try.
In general, this question/answer gives an introduction to reading these errors:
What is a stack trace, and how can I use it to debug my application errors?
Looking at the code, intent should not be null, after all intent.getAction() executes without error.
It seems more likely that you have a problem with ViewFlipper, getting some "Receiver not registered" exception in the nested stack trace:
java.lang.IllegalArgumentException: Receiver not registered: android.widget.ViewFlipper$1#40597cc0
Maybe this question can point you in the right direction:
ViewFlipper : Receiver not registered