Using LocationListener (with google play service) as service consume too much battery (Android 4.4.2) - gps

I have a service that returns the current position every 30 seconds, my problem is that the service consumes about 40% of the battery. The GPS icon is always active, even if I increase the time interval. I see this problem with my Nexus 4 android 4.4.2. Once the callback OnLocationChanged is called, the GPS is awake all the time and this consumes the entire battery. With my other Phone Nexus One android 2.2.3 , I do not see this problem, the GPS turns on every 30 seconds and turns off. And I have no battery consommation. The service use Location Request, with .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY), excepted to use GPS and Network and is not the case. I thinks there is a problem with android 4.4.2 or is Google play service
Here my service code:
public class MyServiceGpsDebug extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,LocationListener
{
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 MyServiceGpsDebug getServerInstance()
{
return MyServiceGpsDebug.this;
}
}
#Override
public void onCreate()
{
super.onCreate();
mInProgress = false;
// 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(Constants.UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(Constants.FASTEST_INTERVAL);
servicesAvailable = servicesConnected();
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)
{
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Started", Constants.LOG_FILE);
mInProgress = true;
mLocationClient.connect();
}
return START_STICKY;
}
private void setUpLocationClientIfNeeded()
{
if(mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
}
#Override
public void onLocationChanged(Location location)
{
// Report to the UI that the location was updated
String msg = Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude());
Log.d("debug", msg);
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
appendLog(msg, Constants.LOCATION_FILE);
}
#Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
public String getTime()
{
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return mDateFormat.format(new Date());
}
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(this);
// 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();
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Stopped", Constants.LOG_FILE);
super.onDestroy();
}
#Override
public void onConnected(Bundle bundle)
{
// Request location updates using static settings
mLocationClient.requestLocationUpdates(mLocationRequest, this);
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Connected", Constants.LOG_FILE);
}
#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();
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected", Constants.LOG_FILE);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
mInProgress = false;
if (connectionResult.hasResolution())
{
// If no resolution is available, display an error dialog
} else {
}
}
public final class Constants
{
// Milliseconds per second
private static final int MILLISECONDS_PER_SECOND = 1000;
// Update frequency in seconds
private static final int UPDATE_INTERVAL_IN_SECONDS = 60;
// Update frequency in milliseconds
public 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 = 60;
// A fast frequency ceiling in milliseconds
public static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
// Stores the lat / long pairs in a text file
public static final String LOCATION_FILE = "sdcard/location.txt";
// Stores the connect / disconnect data in a text file
public static final String LOG_FILE = "sdcard/log.txt";
/**
* Suppress default constructor for noninstantiability
*/
private Constants() {
throw new AssertionError();
}
}
}

I have similar problem with Nexus 4. My app has a service which uses location updates (fusion location or android providers, not both). Everything works OK for all android phones but in Nexus4 after some time the phone gets hot and slow even if i kill the app (through DDMS, 100% stopped). The only solution is to kill Google play services .
I think that there is a bug in play services for nexus 4. There is a dirty solution to kill Google Play Services every 30mins for example if phone=nexus4, but i do not know if it is possible

Related

(React Native) Huawei Location Kit - is there any way to know if network location services setting switch off?

to make our apps working indoor to fetch location we need Network Location Services switch to be on
And we're using this function to detect any setting that still off
We noticed the response which is LocationSettingsStates, when the switch on or off is always true
Am I using wrong function to detect it??
The class and methods mentioned in the original post are the right ones to be used for checking network location service availability.
Please refer to a partial code extracted from Huawei sample code obtained from Github
public void checkSettings(View view) {
new Thread() {
#Override
public void run() {
try {
CheckSettingsRequest checkSettingsRequest = new CheckSettingsRequest();
LocationRequest locationRequest = new LocationRequest();
checkSettingsRequest.setLocationRequest(locationRequest);
checkSettingsRequest.setAlwaysShow(false);
checkSettingsRequest.setNeedBle(false);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(checkSettingsRequest.getLocationRequest())
.setAlwaysShow(checkSettingsRequest.isAlwaysShow())
.setNeedBle(checkSettingsRequest.isNeedBle());
settingsClient.checkLocationSettings(builder.build())
.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
#Override
public void onComplete(Task<LocationSettingsResponse> task) {
if (task != null && task.isSuccessful()) {
LocationSettingsResponse response = task.getResult();
if (response == null) {
return;
}
LocationSettingsStates locationSettingsStates =
response.getLocationSettingsStates();
stringBuilder.append(",\nisLocationPresent=")
.append(locationSettingsStates.isLocationPresent());
stringBuilder.append(",\nisLocationUsable=")
.append(locationSettingsStates.isLocationUsable());
stringBuilder.append(",\nisNetworkLocationUsable=")
.append(locationSettingsStates.isNetworkLocationUsable());
stringBuilder.append(",\nisNetworkLocationPresent=")
.append(locationSettingsStates.isNetworkLocationPresent());
stringBuilder.append(",\nisHMSLocationUsable=")
.append(locationSettingsStates.isHMSLocationUsable());
stringBuilder.append(",\nisHMSLocationPresent=")
.append(locationSettingsStates.isHMSLocationPresent());
LocationLog.i(TAG, "checkLocationSetting onComplete:" + stringBuilder.toString());
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
LocationLog.i(TAG, "checkLocationSetting onFailure:" + e.getMessage());
int statusCode = 0;
if (e instanceof ApiException) {
statusCode = ((ApiException) e).getStatusCode();
}
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
android.util.Log.i(TAG,
"Location settings are not satisfied. Attempting to upgrade "
+ "location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
if (e instanceof ResolvableApiException) {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(CheckSettingActivity.this, 0);
}
} catch (IntentSender.SendIntentException sie) {
android.util.Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
default:
break;
}
}
});
} catch (Exception e) {
LocationLog.i(TAG, "checkLocationSetting exception:" + e.getMessage());
}
}
}.start();
}
The execution results when “network location service” is turned on and off are shown below. It shows the state with true and false respectively.
In some phone, LocationSettings interface may not be able to get the exact state.
You can set the Priority to be PRIORITY_BALANCED_POWER_ACCURACY and use requestLocationUpdatesWithCallback interface to get location update.
If the network location is not enabled, you will get the error code NETWORK_LOCATION_SERVICES_DISABLED 10105.
Then it means the switch is not enabled.

Getting null value from method outside OnCreate on real device

I have this quite simple app, to upload pictures to Firebase directly from camera, written following the original documentation from Android developpers page. It works very well on emulators, but on my Galaxy S4 it crashes. The variable imageFileName gets null on onActivityResult, but only in GS4. Here is what is get in emulators:
I/TAG 0:: FILENAME JPEG_20170420_005617_
I/TAG 1:: FILENAME JPEG_20170420_005617_
And here is what is get in GS4:
I/TAG 0:: FILENAME JPEG_20170420_005617_
I/TAG 1:: FILENAME null
Why it gets null out of nothing? Why on S4? Without this value I cant putFile to Firebase. Only with GS4.
Thanks for your help.
private FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
private StorageReference mStorage;
private Button mSelect, mCam;
public Uri uri, photoURI;
private String imageFileName;
private ProgressDialog mProgressDialog;
private static final int GALLERY_INTENT = 2;
private static final int CAMERA_REQUEST_CODE = 1;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStorage = FirebaseStorage.getInstance().getReference();
mSelect = (Button) findViewById(R.id.first_but);
mCam = (Button) findViewById(R.id.sec_but);
mProgressDialog = new ProgressDialog(this);
mCam.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//startActivityForResult(intent, CAMERA_REQUEST_CODE);
dispatchTakePictureIntent();
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
Log.i("TAG 1: ", "FILENAME " + imageFileName);
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
Log.i("TAG 0: ", "FILENAME " + imageFileName);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Weirdly, what solved the probem was adding this to AdroidManifest.xml
<activity
android:name=".YourActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="portrait" >
</activity>
Thanks to #Janine Kroser
original post: Photo capture Intent causes NullPointerException on Samsung phones only
I still would like some explanation to that, other than "Samsung is weird". Is it possible that the orientation change would destroy some activity containing data?

Accessing activity 2 while foreground is activity 1 (either using OOP or Service in XAMARIN)

i code this from a tutorial for locating your location (but I already made some changes)
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Locations;
using System.Collections.Generic;
using Android.Util;
using System.Linq;
using Java.Lang;
using System.Threading.Tasks;
using System;
using Android.Views;
using Android.Content;
namespace LocatorApp
{
[Activity(Label = "Locator", MainLauncher = true, Icon = "#drawable/locator_ico")]
public class LocatorApp : Activity, ILocationListener
{
static readonly string TAG = "X:" + typeof(LocatorApp).Name;
TextView _addressText;
Location _currentLocation;
LocationManager _locationManager;
Address address;
string _locationProvider;
TextView _locationText;
private double latitude = 0;
private double longitude = 0;
public Location getCurrentLocation() { return _currentLocation; }
public double getLatitude() { return latitude; }
public double getLongitude() { return longitude; }
public Address getAddress() { return address; }
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
_addressText = FindViewById<TextView>(Resource.Id.address_text);
_locationText = FindViewById<TextView>(Resource.Id.location_text);
FindViewById<TextView>(Resource.Id.get_address_button).Click += AddressButton_OnClick;
InitializeLocationManager();
}
public void InitializeLocationManager()
{
_locationManager = (LocationManager)GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Coarse,
PowerRequirement = Power.Medium
};
IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = string.Empty;
}
Log.Debug(TAG, "Using " + _locationProvider + ".");
}
async void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
Toast.MakeText(this, "Still waiting for location.", ToastLength.Short).Show();
}
else
{
try
{
var geoUri = Android.Net.Uri.Parse("geo:" + _currentLocation.Latitude + "," + _currentLocation.Longitude);
var mapIntent = new Intent(Intent.ActionView, geoUri);
StartActivity(mapIntent);
}
catch (System.Exception e)
{
Toast.MakeText(this, "Sorry, there is a problem with geomapping.", ToastLength.Short).Show();
}
}
}
async Task<Address> ReverseGeocodeCurrentLocation()
{
try
{
Geocoder geocoder = new Geocoder(this);
IList<Address> addressList =
await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10);
Address address = addressList.FirstOrDefault();
return address;
}
catch (System.Exception e)
{
throw;
}
return null;
}
void DisplayAddress(Address address)
{
if (address != null)
{
StringBuilder deviceAddress = new StringBuilder();
for (int i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceAddress.Append(address.GetAddressLine(i));
}
// Remove the last comma from the end of the address.
_addressText.Text = "Address: "+deviceAddress.ToString();
}
else
{
_addressText.Text = "Unable to determine the address. Try again in a few minutes.";
}
}
public async void OnLocationChanged(Location location)
{
Toast.MakeText(this, "Location changed.", ToastLength.Short).Show();
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location. Try again in a short while.";
}
else
{
try
{
_locationText.Text = "Location: " + string.Format("{0:f6},{1:f6}", _currentLocation.Latitude, _currentLocation.Longitude);
Address address = await ReverseGeocodeCurrentLocation();
DisplayAddress(address);
var nMgr = (NotificationManager)GetSystemService(NotificationService);
var notification = new Notification(Resource.Drawable.Icon, "Message from LocatorApp");
var pendingIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(LocatorApp)), 0);
notification.SetLatestEventInfo(this, "LocatorApp", "Location changed!", pendingIntent);
nMgr.Notify(0, notification);
}
catch (Java.Lang.Exception e)
{
_addressText.Text = "Unable to determine the address. Try again in a few minutes.";
Toast.MakeText(this, "Error Occured On Geocoder!", ToastLength.Short).Show();
Log.Error(TAG, e.Message);
}
}
}
public void OnProviderDisabled(string provider) { }
public void OnProviderEnabled(string provider) { }
public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
protected override void OnResume()
{
base.OnResume();
if (_locationManager.IsProviderEnabled(_locationProvider))
{
_locationManager.RequestLocationUpdates(_locationProvider, 100, 0, this);
Toast.MakeText(this, _locationProvider.ToString(), ToastLength.Short).Show();
}
else
{
Toast.MakeText(this, "There is a problem with "+_locationProvider.ToString()+" provider.", ToastLength.Short).Show();
}
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
}
}
(i'm just having my experiment)
what I want is to run activity B while foreground is in activity A, just like a basic OOP . but my problem is, I don't know how to make it run. I can't also jump to activity B since it has an oncreate method. I instantiated it and can get the variables values but they are null (seems there is no process happened) . What can be a best solution for this.
note: I am currently looking how to use service for background processing but also i don't know how to run this code after I typed it from a tutorial :( there is only a tutorial for creating a service part but no tutorial for buttons to access it :(
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Util;
using System.Threading;
namespace LocatorApp
{
[Service]
class SimpleService : Service
{
static readonly string TAG = "X:" + typeof(SimpleService).Name;
static readonly int TimerWait = 4000;
Timer _timer;
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Log.Debug(TAG, "OnStartCommand called at {2}, flags={0}, startid={1}", flags, startId, DateTime.UtcNow);
_timer = new Timer(o => { Log.Debug(TAG, "Hello from SimpleService. {0}", DateTime.UtcNow); },
null,
0,
TimerWait);
return StartCommandResult.NotSticky;
}
public override void OnDestroy()
{
base.OnDestroy();
_timer.Dispose();
_timer = null;
Log.Debug(TAG, "SimpleService destroyed at {0}.", DateTime.UtcNow);
}
public override IBinder OnBind(Intent intent)
{
// This example isn't of a bound service, so we just return NULL.
return null;
}
}
}
I want to know both (OOP way and service way) since not at all time we are required to use the service.
what I want is to run activity B while foreground is in activity A, just like a basic OOP . but my problem is, I don't know how to make it run. I can't also jump to activity B since it has an oncreate method.
You can call Context.StartActivity inside your Activity with following codes:
StartActivity(new Android.Content.Intent(this, typeof(ActivityB)));
And StartActivity will call OnCreate method in ActivityB to create a new instance of ActivityB.
For details about Starting Activities, please refer to Starting Activities and Getting Results.
I am currently looking how to use service for background processing but also i don't know how to run this code after I typed it from a tutorial :( there is only a tutorial for creating a service part but no tutorial for buttons to access it :(
Similar like Activity Context.StartService offers a way to start a Service:
StartService (new Intent (this, typeof(DemoService)));
This will call the OnStartCommand method inside your Service class.
For details about usage of Service, please refer to Implementing a Service.

android media player connecting status with audio streaming link(ie 2%,4%...100% then online radio start to play) in android

how i get buffering status while media player trying to connect audio streaming link(ie 2%,4%...100% then online radio start to play) in android.
this is my code.
but i have no idea how i solve my problem.thanks is advance to any kind of help.
player.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
playSeekBar.setSecondaryProgress(percent);
Log.i("Buffering", "" + percent);
}
});
i solve this problem. here is the link. http://coderfriend.blogspot.com/
as per request here i share blog content..
when user click play button to play radio then i want to show connecting status(buffering 1%,2%.. 99%). when status will be 100% radio start to play. i was face problem to solve this. so here i share this code for all.
//at first create this class
public class StreamingMediaPlayer {
private static final int INTIAL_KB_BUFFER = 96*10/8;//assume 96kbps*10secs/8bits per byte
private TextView textStreamed;
private ImageButton playButton;
private ProgressBar progressBar;
// Track for display by progressBar
private long mediaLengthInKb, mediaLengthInSeconds;
private int totalKbRead = 0;
// Create Handler to call View updates on the main UI thread.
private final Handler handler = new Handler();
private MediaPlayer mediaPlayer;
private File downloadingMediaFile;
private boolean isInterrupted;
private Context context;
private int counter = 0;
public StreamingMediaPlayer(Context context,TextView textStreamed, ImageButton playButton, Button streamButton,ProgressBar progressBar)
{
this.context = context;
this.textStreamed = textStreamed;
this.playButton = playButton;
this.progressBar = progressBar;
}
/**
* Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available.
*/
public void startStreaming(final String mediaUrl, long mediaLengthInKb, long mediaLengthInSeconds) throws IOException {
this.mediaLengthInKb = mediaLengthInKb;
this.mediaLengthInSeconds = mediaLengthInSeconds;
Runnable r = new Runnable() {
public void run() {
try {
downloadAudioIncrement(mediaUrl);
} catch (IOException e) {
Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e);
return;
}
}
};
new Thread(r).start();
}
/**
* Download the url stream to a temporary location and then call the setDataSource
* for that local file
*/
public void downloadAudioIncrement(String mediaUrl) throws IOException {
URLConnection cn = new URL(mediaUrl).openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null) {
Log.e(getClass().getName(), "Unable to create InputStream for mediaUrl:" + mediaUrl);
}
downloadingMediaFile = new File(context.getCacheDir(),"downloadingMedia.dat");
if (downloadingMediaFile.exists()) {
downloadingMediaFile.delete();
}
FileOutputStream out = new FileOutputStream(downloadingMediaFile);
byte buf[] = new byte[16384];
int totalBytesRead = 0, incrementalBytesRead = 0;
do {
int numread = stream.read(buf);
if (numread <= 0)
break;
out.write(buf, 0, numread);
totalBytesRead += numread;
incrementalBytesRead += numread;
totalKbRead = totalBytesRead/1000;
testMediaBuffer();
fireDataLoadUpdate();
} while (validateNotInterrupted());
stream.close();
if (validateNotInterrupted()) {
fireDataFullyLoaded();
}
}
private boolean validateNotInterrupted() {
if (isInterrupted) {
if (mediaPlayer != null) {
mediaPlayer.pause();
//mediaPlayer.release();
}
return false;
} else {
return true;
}
}
/**
* Test whether we need to transfer buffered data to the MediaPlayer.
* Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler.
*/
private void testMediaBuffer() {
Runnable updater = new Runnable() {
public void run() {
if (mediaPlayer == null) {
// Only create the MediaPlayer once we have the minimum buffered data
if ( totalKbRead >= INTIAL_KB_BUFFER) {
try {
startMediaPlayer();
} catch (Exception e) {
Log.e(getClass().getName(), "Error copying buffered conent.", e);
}
}
} else if ( mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000 ){
// NOTE: The media player has stopped at the end so transfer any existing buffered data
// We test for < 1second of data because the media player can stop when there is still
// a few milliseconds of data left to play
transferBufferToMediaPlayer();
}
}
};
handler.post(updater);
}
private void startMediaPlayer() {
try {
File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
// We double buffer the data to avoid potential read/write errors that could happen if the
// download thread attempted to write at the same time the MediaPlayer was trying to read.
// For example, we can't guarantee that the MediaPlayer won't open a file for playing and leave it locked while
// the media is playing. This would permanently deadlock the file download. To avoid such a deadloack,
// we move the currently loaded data to a temporary buffer file that we start playing while the remaining
// data downloads.
moveFile(downloadingMediaFile,bufferedFile);
Log.e(getClass().getName(),"Buffered File path: " + bufferedFile.getAbsolutePath());
Log.e(getClass().getName(),"Buffered File length: " + bufferedFile.length()+"");
mediaPlayer = createMediaPlayer(bufferedFile);
// We have pre-loaded enough content and started the MediaPlayer so update the buttons & progress meters.
mediaPlayer.start();
startPlayProgressUpdater();
playButton.setEnabled(true);
} catch (IOException e) {
Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e);
return;
}
}
private MediaPlayer createMediaPlayer(File mediaFile)
throws IOException {
MediaPlayer mPlayer = new MediaPlayer();
mPlayer.setOnErrorListener(
new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e(getClass().getName(), "Error in MediaPlayer: (" + what +") with extra (" +extra +")" );
return false;
}
});
// It appears that for security/permission reasons, it is better to pass a FileDescriptor rather than a direct path to the File.
// Also I have seen errors such as "PVMFErrNotSupported" and "Prepare failed.: status=0x1" if a file path String is passed to
// setDataSource(). So unless otherwise noted, we use a FileDescriptor here.
FileInputStream fis = new FileInputStream(mediaFile);
mPlayer.setDataSource(fis.getFD());
mPlayer.prepare();
return mPlayer;
}
/**
* Transfer buffered data to the MediaPlayer.
* NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so
* this method should always be called using a Handler.
*/
private void transferBufferToMediaPlayer() {
try {
// First determine if we need to restart the player after transferring data...e.g. perhaps the user pressed pause
boolean wasPlaying = mediaPlayer.isPlaying();
int curPosition = mediaPlayer.getCurrentPosition();
// Copy the currently downloaded content to a new buffered File. Store the old File for deleting later.
File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".dat");
File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
// This may be the last buffered File so ask that it be delete on exit. If it's already deleted, then this won't mean anything. If you want to
// keep and track fully downloaded files for later use, write caching code and please send me a copy.
bufferedFile.delete();
moveFile(downloadingMediaFile,bufferedFile);
// Pause the current player now as we are about to create and start a new one. So far (Android v1.5),
// this always happens so quickly that the user never realized we've stopped the player and started a new one
mediaPlayer.pause();
// Create a new MediaPlayer rather than try to re-prepare the prior one.
mediaPlayer = createMediaPlayer(bufferedFile);
mediaPlayer.seekTo(curPosition);
// Restart if at end of prior buffered content or mediaPlayer was previously playing.
// NOTE: We test for < 1second of data because the media player can stop when there is still
// a few milliseconds of data left to play
boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000;
if (wasPlaying || atEndOfFile){
mediaPlayer.start();
}
// Lastly delete the previously playing buffered File as it's no longer needed.
oldBufferedFile.delete();
}catch (Exception e) {
Log.e(getClass().getName(), "Error updating to newly loaded content.", e);
}
}
private void fireDataLoadUpdate() {
Runnable updater = new Runnable() {
public void run() {
if((totalKbRead>19)&&(totalKbRead<120))
textStreamed.setText((totalKbRead-19 + "% Buffering"));//show buffering status.. ie 1%,2%. in ui
else if(totalKbRead<19)
textStreamed.setText(("Connecting..."));
else
textStreamed.setText((""));
float loadProgress = ((float)totalKbRead/(float)mediaLengthInKb);
progressBar.setSecondaryProgress((int)(loadProgress*100));
}
};
handler.post(updater);
}
private void fireDataFullyLoaded() {
Runnable updater = new Runnable() {
public void run() {
transferBufferToMediaPlayer();
// Delete the downloaded File as it's now been transferred to the currently playing buffer file.
downloadingMediaFile.delete();
textStreamed.setText(("Audio full loaded: " + totalKbRead + " Kb read"));
}
};
handler.post(updater);
}
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
public void startPlayProgressUpdater() {
float progress = (((float)mediaPlayer.getCurrentPosition()/1000)/mediaLengthInSeconds);
progressBar.setProgress((int)(progress*100));
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
startPlayProgressUpdater();
}
};
handler.postDelayed(notification,1000);
}
}
public void interrupt() {
playButton.setEnabled(false);
isInterrupted = true;
validateNotInterrupted();
}
/**
* Move the file in oldLocation to newLocation.
*/
public void moveFile(File oldLocation, File newLocation)
throws IOException {
if ( oldLocation.exists( )) {
BufferedInputStream reader = new BufferedInputStream( new FileInputStream(oldLocation) );
BufferedOutputStream writer = new BufferedOutputStream( new FileOutputStream(newLocation, false));
try {
byte[] buff = new byte[8192];
int numChars;
while ( (numChars = reader.read( buff, 0, buff.length ) ) != -1) {
writer.write( buff, 0, numChars );
}
} catch( IOException ex ) {
throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath());
} finally {
try {
if ( reader != null ){
writer.close();
reader.close();
}
} catch( IOException ex ){
Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
}
}
} else {
throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
}
}
}
//now copy the below code in activity
StreamingMediaPlayer audioStreamer =
new StreamingMediaPlayer(this,textStreamed,playButton,
streamButton,progressBar);
audioStreamer.startStreaming("your streaming station name",5208, 216);
i think this helps you :)

How to add and configure asmack in android

Please can you help with a break down of how you got asmack working in your android. I cant get it to work for my application. I keep geting java.lang.verifyError.
Be sure to include latest version i.e. asmack-android-17-0.8.3 of asmack library in libs folder.
Adding this might remove java.lang.VerifyError.
I do it the following way, it works perfectly.
public void login(View view)
{
new Connection().execute("username", "password");
}
private class Connection extends AsyncTask<String, Void, Integer>
{
private static final int CONNECTION_FAILURE = 0;
private static final int LOGIN_FAILURE = 1;
private static final int SUCCESS = 2;
#Override
protected Integer doInBackground(String... strings)
{
ConnectionConfiguration conConfig = new ConnectionConfiguration("192.168.1.100", 5222, "domain");
connection = new XMPPConnection(conConfig);
try
{
connection.connect();
Log.i("AppName", "CONNECTED TO " + connection.getHost());
}
catch(Exception e)
{
Log.e("AppName", e.getMessage());
return CONNECTION_FAILURE;
}
try
{
connection.login(strings[0], strings[1]);
Log.i("AppName", "LOGGED IN AS " + connection.getUser());
Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
}
catch(Exception e)
{
Log.e("AppName", e.getMessage());
return LOGIN_FAILURE;
}
return SUCCESS;
}
}