xamarin.ios mp3 streaming from url stops before its end - c#

I'm developing an ios app with xamarin, that contains some mp3 files to stream in the app.
i used thissample, and it seems to work fine...
but the mp3 stops before its end, always at around 2' 30"
this is the code i used:
public partial class PlayerViewController : UIViewController
{
NSTimer updatingTimer;
StreamingPlayback player;
public event EventHandler<ErrorArg> ErrorOccurred;
public string SourceUrl { get; private set; }
public string Title { get; private set; }
public PlayerOption PlayerOption { get; private set; }
public bool IsPlaying { get; private set; }
public PlayerViewController (PlayerOption playerOption, string sourceUrl, string title) : base ("PlayerViewController", null)
{
PlayerOption = playerOption;
SourceUrl = sourceUrl;
Title = title;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.View = View;
volumeSlider.TouchUpInside += SetVolume;
playPauseButton.TouchUpInside += PlayPauseButtonClickHandler;
headerMusic.Text = this.Title;
}
void SetVolume (object sender, EventArgs e)
{
if (player == null)
return;
player.Volume = volumeSlider.Value;
}
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
Title = PlayerOption == PlayerOption.Stream ? "Stream " : "Stream & Save";
playPauseButton.TitleLabel.Text = "Pause";
timeLabel.Text = string.Empty;
// Create a shared intance session & check
var session = AVAudioSession.SharedInstance ();
if (session == null) {
var alert = new UIAlertView ("Playback error", "Unable to playback stream", null, "Cancel");
alert.Show ();
alert.Clicked += (object sender, UIButtonEventArgs e) => alert.DismissWithClickedButtonIndex (0, true);
} else {
StartPlayback ();
IsPlaying = true;
// Set up the session for playback category
NSError error;
session.SetCategory (AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.DefaultToSpeaker);
session.OverrideOutputAudioPort (AVAudioSessionPortOverride.Speaker, out error);
}
}
public override void ViewDidDisappear (bool animated)
{
base.ViewDidDisappear (animated);
if (updatingTimer != null)
updatingTimer.Invalidate ();
if (player != null) {
player.FlushAndClose ();
player = null;
}
}
void PlayPauseButtonClickHandler (object sender, EventArgs e)
{
if (player == null)
return;
if (IsPlaying)
player.Pause ();
else
player.Play ();
var title = IsPlaying ? "Play" : "Pause";
playPauseButton.SetTitle (title, UIControlState.Normal);
playPauseButton.SetTitle (title, UIControlState.Selected);
IsPlaying = !IsPlaying;
}
void StartPlayback ()
{
try {
var request = (HttpWebRequest)WebRequest.Create (SourceUrl);
request.BeginGetResponse (StreamDownloadedHandler, request);
} catch (Exception e) {
string.Format ("Error: {0}", e.ToString ());
}
}
void RaiseErrorOccurredEvent (string message)
{
var handler = ErrorOccurred;
if (handler != null)
handler (this, new ErrorArg { Description = message });
}
void StreamDownloadedHandler (IAsyncResult result)
{
var buffer = new byte [8192];
int l = 0;
int inputStreamLength;
double sampleRate = 0;
Stream inputStream;
AudioQueueTimeline timeline = null;
var request = result.AsyncState as HttpWebRequest;
try {
var response = request.EndGetResponse (result);
var responseStream = response.GetResponseStream ();
if (PlayerOption == PlayerOption.StreamAndSave)
inputStream = GetQueueStream (responseStream);
else
inputStream = responseStream;
using (player = new StreamingPlayback ()) {
player.OutputReady += delegate {
timeline = player.OutputQueue.CreateTimeline ();
sampleRate = player.OutputQueue.SampleRate;
};
InvokeOnMainThread (delegate {
if (updatingTimer != null)
updatingTimer.Invalidate ();
updatingTimer = NSTimer.CreateRepeatingScheduledTimer (0.5, (timer) => RepeatingAction (timeline, sampleRate));
});
while ((inputStreamLength = inputStream.Read (buffer, 0, buffer.Length)) != 0 && player != null) {
l += inputStreamLength;
player.ParseBytes (buffer, inputStreamLength, false, l == (int)response.ContentLength);
InvokeOnMainThread (delegate {
progressBar.Progress = l / (float)response.ContentLength;
});
}
}
} catch (Exception e) {
RaiseErrorOccurredEvent ("Error fetching response stream\n" + e);
Debug.WriteLine (e);
InvokeOnMainThread (delegate {
if (NavigationController != null)
NavigationController.PopToRootViewController (true);
});
}
}
void RepeatingAction (AudioQueueTimeline timeline, double sampleRate)
{
var queue = player.OutputQueue;
if (queue == null || timeline == null)
return;
bool disc = false;
var time = new AudioTimeStamp ();
queue.GetCurrentTime (timeline, ref time, ref disc);
playbackTime.Text = FormatTime (time.SampleTime / sampleRate);
}
string FormatTime (double time)
{
double minutes = time / 60;
double seconds = time % 60;
return String.Format ("{0}:{1:D2}", (int)minutes, (int)seconds);
}
Stream GetQueueStream (Stream responseStream)
{
var queueStream = new QueueStream (Environment.GetFolderPath (Environment.SpecialFolder.Personal) + "/copy.mp3");
var t = new Thread ((x) => {
var tbuf = new byte [8192];
int count;
while ((count = responseStream.Read (tbuf, 0, tbuf.Length)) != 0)
queueStream.Push (tbuf, 0, count);
});
t.Start ();
return queueStream;
}
}
how can i solve this problem?
thanks in advance

Had the same issue.
Open the StreamingPlayback.cs file
Change the variable
int bufferSize = 128 * 1024
Into
int bufferSize = 128 * 128
Or try other sizes..
It worked for me

Related

List of Stopwatches - restarting begins all timers due to binding

Hope you can help ... I have a list of activities which use a stopwatch to track each one of their activity durations. When I tap an activity in my list, it starts the stopwatch for the activity tapped and when I tap the activity row again it stops the stopwatch and resets it.
However when I then tap another activity, although it is really only updating the duration for the activity tapped in the backend, the frontend UI updates all of the activities timers with the same activity time tapped because they are binded to the same activityduration element. I don't know how to only change the activity duration for the activity tapped in the front end. Could anyone advise on how to do this without re-structuring my model/collection? Or will I have to make a subnest for the activity name in my collection?
On tap event in code behind:-
public async void OnActivityTap(object sender, EventArgs e)
{
var item = (ViewCell)sender;
UserActivities.Activities myactivitiesModel = item.BindingContext as UserActivities.Activities;
if (myactivitiesModel == null)
{return;}
// OnPropertyChanged("ActivityDuration");
// mystopwatch.Reset();
//ViewModel.getUserActivities();
foreach (var x in ViewModel.UserActivitiesList) {
if(x.ActivityName == myactivitiesModel.ActivityName) {
int seconds = 1;
//if the activity is not enabled and the activity is tapped
if (myactivitiesModel.ActivityEnabled == false)
{
//enable the activity and start the stopwatch
myactivitiesModel.ActivityEnabled = true;
//Get the current duration and add it onto the stopwatch start time
ts = x.ActivityDuration;
//Reset the stopwatch back to zero
mystopwatch = new Stopwatch();
//Start the stopwatch
mystopwatch.Reset();
mystopwatch.Start();
while (myactivitiesModel.ActivityEnabled == true)
{
Device.StartTimer(TimeSpan.FromSeconds(seconds), () =>
{
myactivitiesModel.ActivityDuration = (mystopwatch.Elapsed + ts);
return true;
});
return;
}
}
else if (myactivitiesModel.ActivityEnabled == true)
{
//disable the activity and stop the stopwatch
x.ActivityEnabled = false;
//Stop the clock
mystopwatch.Stop();
//Store activity time stopped
await MongoService.UpdateUserActivityTime(userIdentity, myactivitiesModel.ActivityName, x.ActivityDuration);
//Store the time stopped in the UserActivitiesList binded to the UI list
x.ActivityDuration = myactivitiesModel.ActivityDuration;
OnPropertyChanged("ActivityDuration");
return;
}
} //end of if activityName Tapped
} //end of foreach
} //end of OnTap Activity
Model:
public class UserActivities : INotifyPropertyChanged
{
[BsonId, BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
string _foreignUserID;
[BsonElement("foreignUserID")]
public string foreignUserID
{
get => _foreignUserID; set
{
if (_foreignUserID == value)
return;
_foreignUserID = value;
HandlePropertyChanged();
}
}
[BsonElement("activities")]
public ObservableCollection<Activities> UserTimedActivities { get; set; }
public class Activities : INotifyPropertyChanged
{
string _activityName;
[BsonElement("activityName")]
public string ActivityName
{
get => _activityName; set
{
if (_activityName == value)
return;
_activityName = value;
HandlePropertyChanged();
}
}
TimeSpan _activityDuration;
[BsonElement("activityDuration")]
public TimeSpan ActivityDuration
{
get => _activityDuration; set
{
if (_activityDuration == value)
return;
_activityDuration = value;
HandlePropertyChanged();
}
}
TimeSpan _activityGoalDuration;
[BsonElement("activityGoalDuration")]
public TimeSpan ActivityGoalDuration
{
get => _activityGoalDuration; set
{
if (_activityGoalDuration == value)
return;
_activityGoalDuration = value;
HandlePropertyChanged();
}
}
Boolean _activityEnabled;
[BsonElement("activityEnabled")]
public Boolean ActivityEnabled
{
get => _activityEnabled; set
{
if (_activityEnabled == value)
return;
_activityEnabled = value;
HandlePropertyChanged();
}
}
public Activities(string activityname, TimeSpan activityduration, TimeSpan activitygoalduration, Boolean activityenabled ) {
ActivityName = activityname;
ActivityDuration = activityduration;
ActivityGoalDuration = activitygoalduration;
ActivityEnabled = activityenabled;
}
void HandlePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public UserActivities(ObservableCollection<Activities> usertimedactivities)
{
UserTimedActivities = usertimedactivities;
}
public event PropertyChangedEventHandler PropertyChanged;
void HandlePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel method to compile list-
public async void getUserActivities()
{
var userActivities = await MongoService.GetUserActivityData(userIdentity);
try
{
if (IsBusy)
return;
IsBusy = true;
UserActivitiesList.Clear();
foreach (var x in userActivities)
{
foreach(var y in x.UserTimedActivities) {
//foreach (var y in x.userActivities)
UserActivitiesList.Add(y);
}
}
}
catch (Exception ex)
{
IsBusy = false;
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
2. Alternative Timer method suggested by Jason (doesn't get elapsed time or update UI):
public async void OnActivityTap(object sender, EventArgs e)
{
var item = (ViewCell)sender;
UserActivities.Activities myactivitiesModel = item.BindingContext as UserActivities.Activities;
if (myactivitiesModel == null)
{ return; }
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityName == myactivitiesModel.ActivityName)
{
if (x.ActivityEnabled == false)
{
x.ActivityEnabled = true;
timer.Enabled = true;
timer.Start();
timer.Elapsed += OnTimedEvent;
x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
else
{
x.ActivityEnabled = false;
timer.Enabled = false;
timer.Stop();
x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
**3. Alternative approach with stopwatch - does work but doesn't update UI until tapped **
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityName == myactivitiesModel.ActivityName)
{
if (x.ActivityEnabled == false)
{
x.ActivityEnabled = true;
//timer.Enabled = true;
mystopwatch.Restart();
mystopwatch.Start();
x.ActivityDuration = mystopwatch.Elapsed + x.ActivityDuration;
NotifyPropertyChanged("ActivityDuration");
//timer.Elapsed += OnTimedEvent;
//x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
else
{
x.ActivityEnabled = false;
//timer.Enabled = false;
mystopwatch.Stop();
x.ActivityDuration = mystopwatch.Elapsed + x.ActivityDuration;
NotifyPropertyChanged("ActivityDuration");
//x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
I think you're making this way too complicated. I would create a single timer and do something like this
using System.Timers;
...
// 100ms == .1s
double interval = 100;
// CREATE ONE TIMER FOR ALL ACTIVITIES
Timer timer = new Timer(interval);
timer.Elapsed += UpdateTimers;
timer.Start();
...
private void UpdateTimers(object sender, EventArgs a)
{
// this is psudocode, update for your model
foreach(var a in Activities)
{
// if activity is selected
if (a.Active) {
// update the elapsed time
a.Elapsed = a.Elapsed.Add(new Timespan(0,0,0,0,interval));
}
}
}
Final Solution as implemented by OP
public page()
{
timer.Start();
timer.Elapsed += UpdateTimers;
}
private void UpdateTimers(object sender, EventArgs a)
{
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityEnabled)
{
x.ActivityDuration = x.ActivityDuration.Add(new
TimeSpan(0, 0, 0, 0, (int)interval));
}
}
}

I want to get the location changes, but I get JNI DETECTED ERROR IN APPLICATION in GoogleApiClient

I want to get the location changes by the method of OnLocationChanged, I used the OnMyLocationChanged before but I see that this method is already in disuse, but with the new meotodo it marks me error when assigning the mGoogleApiClient variable
namespace FuncionesAndroid.Droid
{
[Activity(Label = "MainMapa")]
public class MainMapa : Activity, IOnMapReadyCallback, IOnMyLocationClickListener, IOnMyLocationButtonClickListener, Android.Gms.Location.ILocationListener, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener
{
private string _tag = "MainMapa";
GoogleMap mapa = null;
DataBase db = new DataBase();
private LocationRequest locationRequest;
static GoogleApiClient mGoogleApiClient;
public static int MILISEGUNDOS_POR_SECUNDOS = 1000;
public static int MINUTO = 60 * MILISEGUNDOS_POR_SECUNDOS;
//private IFusedLocationProviderApi locationProvider = LocationServices.FusedLocationApi;
public async void OnMapReady(GoogleMap googleMap)
{
mapa = googleMap;
googleMap.MyLocationEnabled = true;
googleMap.SetOnMyLocationButtonClickListener(this);
googleMap.SetOnMyLocationClickListener(this);
googleMap.SetMinZoomPreference(6.0F);
//Opcional
googleMap.SetLatLngBoundsForCameraTarget(new LatLngBounds(new LatLng(14.399838, -119.346947),new LatLng(30.706694, -83.355215)));
googleMap.UiSettings.ZoomControlsEnabled = true;
googleMap.UiSettings.CompassEnabled = true;
locationRequest = new LocationRequest();
locationRequest.SetInterval(MINUTO);
locationRequest.SetFastestInterval(15 * MILISEGUNDOS_POR_SECUNDOS);
locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
try
{
mGoogleApiClient = new GoogleApiClient.Builder(this)
.AddConnectionCallbacks(this)
.AddOnConnectionFailedListener(this)
.AddApi(LocationServices.API)
.Build();
}
catch (Exception e)
{
Log.Debug(_tag, e.Message);
}
googleMap.MoveCamera(CameraUpdateFactory.ZoomIn());
CargarMarcadores();
CentrarMyUbicacion();
}
private void GuardarRutas(ArrayList rutas, int idInicio, int idFin)
{
foreach (ArrayList path in rutas)
{
foreach (Dictionary<String, Double> punto in path)
{
Model.Polyline polyline = new Model.Polyline()
{
id_inicio = idInicio,
id_fin = idFin,
lat = punto["lat"],
lon = punto["lon"]
};
db.InsertarDatoPolyline(polyline, this);
}
}
}
public void CargarMarcadores()
{
BitmapDrawable bitmapClienteDraw = (BitmapDrawable)GetDrawable(Resource.Mipmap.marker_map_us);
Bitmap bitmapCliente = bitmapClienteDraw.Bitmap;
Bitmap smallMarkerCliente = Bitmap.CreateScaledBitmap(bitmapCliente, 60, 90, false);
List<ClientesGps> clientesGps;
clientesGps = db.selectTablaClientesGps(this);
Location miUbicacion = ObtenerUbicacionActual();
foreach (ClientesGps cliente in clientesGps)
{
MarkerOptions clienteMarcador = new MarkerOptions()
.SetPosition(new LatLng(cliente.lat, cliente.lon))
.SetIcon(BitmapDescriptorFactory.FromBitmap(smallMarkerCliente))
.SetTitle(cliente.nombre);
mapa.AddMarker(clienteMarcador);
}
}
public void CentrarMyUbicacion()
{
LocationManager locationManager = (LocationManager)
GetSystemService(Context.LocationService);
Criteria criteria = new Criteria();
criteria.Accuracy = Accuracy.Fine;
Location Ubicación = locationManager.GetLastKnownLocation(locationManager.GetBestProvider(criteria, false));
if (Ubicación != null)
{
LatLng myUbicación = new LatLng(Ubicación.Latitude, Ubicación.Longitude);
mapa.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(myUbicación,15.4F));
}
}
public Location ObtenerUbicacionActual()
{
LocationManager locationManager = (LocationManager)
GetSystemService(Context.LocationService);
Criteria criteria = new Criteria();
criteria.Accuracy = Accuracy.Fine;
Location Ubicación = locationManager.GetLastKnownLocation(locationManager.GetBestProvider(criteria, false));
return Ubicación;
}
public void DibujarRutas(ArrayList rutas, GoogleMap googleMap)
{
PolylineOptions polylineOptions = null;
foreach(ArrayList path in rutas)
{
polylineOptions = new PolylineOptions();
foreach(Dictionary<String, Double> punto in path)
{
double lat, lon;
lat = punto["lat"];
lon = punto["lon"];
polylineOptions.Add(new LatLng(lat, lon));
}
polylineOptions.InvokeWidth(15);
polylineOptions.InvokeColor(Color.Blue);
polylineOptions.Geodesic(true);
}
if(polylineOptions!=null)
{
googleMap.AddPolyline(polylineOptions);
}
else
{
Toast.MakeText(this, "Direcciones no encontradas", ToastLength.Short).Show();
}
}
private async Task<ArrayList> GetUrlAsync(LatLng origin,LatLng dest, String directionMode)
{
String str_origin = "origin=" + origin.Latitude + "," + origin.Longitude;
String str_dest = "destination=" + dest.Latitude + "," + dest.Longitude;
String mode = "mode=" + directionMode;
String parameters = str_origin + "&" + str_dest + "&" + mode;
String output = "json";
JObject json = await Servicios.Servicio.ObtenerRutaGoogleMaps(output, parameters, GetString(Resource.String.GoogleKey));
ArrayList routes = new ArrayList();
JArray jRoutes = null;
JArray jLegs = null;
JArray jSteps = null;
try
{
jRoutes = (JArray)json["routes"];
for (int i = 0; i < jRoutes.Count; i++)
{
jLegs = (JArray)jRoutes[i]["legs"];
ArrayList path = new ArrayList();
for (int j = 0; j < jLegs.Count; j++)
{
jSteps = (JArray)jLegs[j]["steps"];
for (int k = 0; k < jSteps.Count; k++)
{
String polyline = "";
polyline = (String)jSteps[k]["polyline"]["points"];
ArrayList list = decodePolyline(polyline);
for(int l = 0; l < list.Count; l++)
{
Dictionary<String, Double> hm = new Dictionary<string, Double>();
hm.Add("lat", ((LatLng)list[l]).Latitude);
hm.Add("lon", ((LatLng)list[l]).Longitude);
path.Add(hm);
}
}
routes.Add(path);
}
}
return routes;
}
catch (JsonReaderException e)
{
routes = null;
return routes;
}
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MainMapa);
MapFragment mapFragment = (MapFragment)FragmentManager.FindFragmentById(Resource.Id.map);
mapFragment.GetMapAsync(this);
}
protected override void OnResume()
{
base.OnResume();
if(mGoogleApiClient.IsConnected)
{
RequestLocationUpdates();
}
}
protected override void OnStart()
{
base.OnStart();
mGoogleApiClient.Connect();
}
protected override void OnStop()
{
base.OnStop();
mGoogleApiClient.Disconnect();
}
private void RequestLocationUpdates()
{
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, locationRequest, this);
}
protected override void OnPause()
{
base.OnPause();
LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
}
public void OnMyLocationClick(Location location)
{
Toast.MakeText(this, "My Ubicación actual", ToastLength.Short).Show();
}
public bool OnMyLocationButtonClick()
{
Toast.MakeText(this, "Centrando en ubicación actual", ToastLength.Short).Show();
return false;
}
public async void OnLocationChanged(Location location)
{
Toast.MakeText(this, location.ToString(),ToastLength.Short).Show();
}
public void OnConnectionFailed(ConnectionResult result)
{
//throw new NotImplementedException();
}
public void OnConnected(Bundle connectionHint)
{
RequestLocationUpdates();
}
public void OnConnectionSuspended(int cause)
{
//throw new NotImplementedException();
}
}
}
Likewise, I have seen some codes that are not in disuse, that do not use the Google AppClient, but do not explain the use or are not very well documented, if they have some better code I would appreciate it very much
The solution was very simple and silly, I read in another forum, when it comes to GoogleApiClient is normal to fail the first in Xamarin, the right thing is to clean and recompile the solution when it comes to it, thank you very much as you want to read !

how to load multiple URL in android using visual studio c#

I am a developing an application (apk) it is nothing but a display of stored images & bitmap images (url).This is my first application & I am using code by watching different tutorials that i need to code over youtube and searching websites to get help.
Below here is the whole code for application.
namespace androidapk
{
[Activity(Label = "android", MainLauncher = true, Icon = "#drawable/icon")]
public class Activity : Android.App.Activity
{
private ImageView ImageContainer;
// private ImageView UrlContainer;
private int CurrentImage = 0;
// private int CurrentUrl = 0;
private Button nextClick;
private Button backClick;
int[] images = { Resource.Drawable.orange, Resource.Drawable.Icon, Resource.Drawable.images02, Resource.Drawable.buttonarrow, Resource.Drawable.images };
// string[] Urls = { "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiFsZgrhpFIx496REDS7XimTQVo07W6zFwULlNFIO3OpgPNCMc,https://www.google.com.pk/imgres?imgurl=http%3A%2F%2Fpngimg.com%2Fupload%2Fwater_PNG3290.png&imgrefurl=http%3A%2F%2Fpngimg.com%2Fimg%2Fnature%2Fwater&docid=egiWzVBWw_5-bM&tbnid=geXqbWHLhH-PPM%3A&w=1280&h=798&bih=667&biw=1366&ved=0ahUKEwitguqNm8POAhWHWhQKHc_TBewQMwgxKAEwAQ&iact=mrc&uact=8" };
public Action<object, EventArgs> Click { get; private set; }
public int FindViewByIddemoImageview { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
nextClick = (Button)FindViewById(Resource.Id.Btnup);
backClick = (Button)FindViewById(Resource.Id.Btnback);
ImageContainer = (ImageView)FindViewById(Resource.Id.demoImageView);
// UrlContainer = (ImageView)FindViewById();
//Android.Net.Uri url = Android.Net.Uri.Parse("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiFsZgrhpFIx496REDS7XimTQVo07W6zFwULlNFIO3OpgPNCMc");
var imageBitmap = GetImageBitmapFromUrl("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiFsZgrhpFIx496REDS7XimTQVo07W6zFwULlNFIO3OpgPNCMc");
RunOnUiThread(() => ImageContainer.SetImageBitmap(imageBitmap));
nextClick.Click += delegate {
NextImagePic();
// NextImageUrl();
};
backClick.Click += delegate {
BackImagePic();
};
//HapticFeedbackConstants
}
private Bitmap GetImageBitmapFromUrl(string url)
{
Bitmap imageBitmap = null;
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
return imageBitmap;
}
private void NextImagePic()
{
if (CurrentImage == 0)
{
RunOnUiThread(() => ImageContainer.SetImageResource(images[CurrentImage + 1]));
CurrentImage++;
}
else
{
if (CurrentImage < images.Count() - 1)
{
CurrentImage++;
RunOnUiThread(() => ImageContainer.SetImageResource(images[CurrentImage]));
}
else
{
Toast.MakeText(this, "This is last image.", ToastLength.Long).Show();
}
}
}
private void BackImagePic()
{
if (CurrentImage == 0)
{
RunOnUiThread(() => ImageContainer.SetImageResource(images[CurrentImage]));
Toast.MakeText(this, "This is first image.", ToastLength.Long).Show();
}
else
{
CurrentImage--;
RunOnUiThread(() => ImageContainer.SetImageResource(images[CurrentImage]));
}
}
}
}
i have displayed successfully images stored using arrays [] but i want to display multiple images in arrays using URL's I have displayed single image using single URL.

Method that does not proceed until event gets fired

I have a GUI that is linked to several Sensors through COM-Port. I have a Datahandler that makes sure that the received and sent packages have the correct size and content. And then i have a SensorContainer containing all Sensors, firing an event whenever a new sensor is added!
My problem is now:
I need a method, that can initialize all sensors with one click.
And i just cant do it. If I initialize them one by one, it works, but all in one method doesnt work.
My idea is that the packages get mixed and the handler doesnt accept the sensors anymore for initialization. So i tried to make the method wait for the first sensor to be initialized and the proceed, but i have no clue how!
I tried a few things with mulitthreading, but im not really experienced in that field and it didnt work out in the end anyway...
SensorContainerClass:
public static class SensorContainer
{
public static event EventHandler<ContainerEvent> ContainerChanged;
public static ObservableCollection<Sensor> SensorList
{
get { return _sensorList; }
}
public static void AddSensor(Sensor sensor)
{
Sensor sensorExists = GetSensor(sensor.Address);
if (sensorExists == null)
{
Application.Current.Dispatcher.Invoke(() => _sensorList.Add(sensor));
ContainerChanged(null,new ContainerEvent(sensor.Address, true));
}
else
{
Console.WriteLine("It's not possible to add multiple sensors with the same address.");
}
}
public static void RemoveSensor(Sensor sensor)
{
Sensor sensorExists = GetSensor(sensor.Address);
if (sensorExists != null)
{
Application.Current.Dispatcher.Invoke(() => _sensorList.Remove(sensor));
ContainerChanged(null, new ContainerEvent(sensor.Address, false));
}
else
{
Console.WriteLine("No sensor with address " + sensor.Address);
}
}
public static Sensor GetSensor(byte address)
{
foreach (Sensor sensor in _sensorList)
{
if (sensor.Address == address)
{
return sensor;
}
}
return null;
}
// members
private static readonly ObservableCollection<Sensor> _sensorList = new ObservableCollection<Sensor>();
}
DataHandler:
public class DataHandler:ModelBase
{
private const int MAX_TIMER_TIME = 500;
public long answertime_milli;
Timer aTimer;
Stopwatch watch;
Sensor tempSensor;
private byte[] tempFrame;
private bool framePartPendingFlag = false;
public bool framesEqual;
public bool initalisationFlag = false;
public InitType initialisationType;
public byte[] TxFrame
{
get { return txFrame; }
}
public byte TxAddress
{
get { return TxFrame[0]; }
}
public byte TxLength
{
get { return TxFrame[1]; }
}
public byte TxCommand
{
get { return TxFrame[2]; }
}
public byte[] TxData
{
get { return TxFrame.GetRange(3, TxLength - 2); }
}
public byte TxChecksum
{
get { return TxFrame[TxLength - 1]; }
}
private byte[] txFrame;
private bool successfull;
public bool Successfull
{
get
{
return successfull;
}
set
{
if(successfull != value)
{
successfull = value;
this.OnPropertyChanged();
}
}
}
public DataHandler()
{
txFrame = new byte[4] { 0, 0, 0, 0 };
aTimer = new Timer(MAX_TIMER_TIME);
watch = new Stopwatch();
CommandManager.Instance.Init();
InterfaceWrapper.Instance.SerialPort.DataReceived += OnSerialPortReceived;
}
public void InitializeSensor(InitType type, byte address, Int32 serialNumber = 0)
{
if (SensorContainer.GetSensor(address) != null )
{
MessageBox.Show("Sensoraddress already used");
return;
}
foreach(Sensor temp in SensorContainer.SensorList)
{
if(temp.Serialnr == serialNumber)
{
MessageBox.Show("Sensor with the same SerialNumber already initalized");
return;
}
}
byte[] frame;
if (type == InitType.INIT_TO_ONE_DEVICE)
{
Sensor.COM_ADDR_SET_ONE_TX initStruct = new Sensor.COM_ADDR_SET_ONE_TX();
initStruct.Address = address;
frame = createFrame(initStruct, 0xFF, 0x20);
}
else
{
Sensor.COM_ADDR_SET_TO_SN_TX initStruct = new Sensor.COM_ADDR_SET_TO_SN_TX();
initStruct.Address = address;
if (serialNumber == 0)
{
MessageBox.Show("Serialnumber is missing");
return;
}
initStruct.SerialNumber = serialNumber;
frame = createFrame(initStruct, 0x00, 0x22);
}
setTxFrame(frame);
InterfaceWrapper.Instance.SerialPort.SendData(frame);
initalisationFlag = true;
initialisationType = type;
}
public void StartDataTransfer(Sensor sensor, byte commandid)
{
if (sensor == null)
{
MessageBox.Show("No such sensor");
return;
}
Command command = sensor.getCommand(commandid);
if (command == null)
{
MessageBox.Show("Command does not exist");
return;
}
foreach (KeyValuePair<CommandAttribute, Command> pair in sensor.CommandList)
{
if (pair.Value == command)
{
timeout = pair.Key.Timeout;
transmission = pair.Key.Transmission;
break;
}
}
tempSensor = sensor;
if (SensorContainer.GetSensor(sensor.Address) != null)
{
byte[] endFrame = createFrame(command, sensor.Address, commandid);
setTxFrame(endFrame);
if (true)
{
InterfaceWrapper.Instance.SerialPort.SendData(txFrame);
}
}
else
{
MessageBox.Show("Sensor not yet initialized");
}
}
private byte[] createFrame(Command command, byte address, byte commandId)
{
byte[] data = MarshalHelper.Serialize(command);
byte[] frame = new byte[4 + data.Length];
frame[0] = address;
frame[1] = (byte)frame.Length;
frame[2] = commandId;
Buffer.BlockCopy(data, 0, frame, 3, data.Length);
frame[frame.Length - 1] = GenerateChecksum(frame);
return frame;
}
public void OnSerialPortReceived(object sender, ComDataRxEvent e)
{
byte[] data = e.Data;
setRxFrame(data);
}
public void setTxFrame(byte[] _txFrame)
{
Successfull = false;
txFrame = _txFrame;
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = false;
aTimer.Start();
watch.Start();
}
public void setRxFrame(byte[] _rxFrame)
{
if (framePartPendingFlag)
{
byte[] newTempFrame = new byte[tempFrame.Length + _rxFrame.Length];
tempFrame.CopyTo(newTempFrame, 0);
_rxFrame.CopyTo(newTempFrame, tempFrame.Length);
framePartPendingFlag = false;
setRxFrame(newTempFrame);
}
else if (!checkMinLength(_rxFrame))
{
tempFrame = _rxFrame;
framePartPendingFlag = true;
}
else if (!checkBit(_rxFrame))
{
tempFrame = _rxFrame;
framePartPendingFlag = true;
}
else
{
framePartPendingFlag = false;
aTimer.Stop();
watch.Stop();
answertime_milli = watch.ElapsedMilliseconds;
if (!initalisationFlag)
{
if (checkAll(_rxFrame))
{
writeCommandToSensor(_rxFrame);
}
}
else
{
createSensorAfterInitialization(_rxFrame);
}
}
}
private void writeCommandToSensor(byte[] frame)
{
Command expCommand = CommandManager.Instance.GetRxCommand(tempSensor.GetType(), TxCommand);
Command command = MarshalHelper.Deserialize(expCommand, frame.GetRange(3, frame[1] - 2));
tempSensor.setCommand(command);
}
private void createSensorAfterInitialization(byte[] frame)
{
if (initalisationFlag && initialisationType == InitType.INIT_TO_ONE_DEVICE)
{
Sensor.COM_ADDR_SET_ONE_RX expCommand = new Sensor.COM_ADDR_SET_ONE_RX();
Sensor.COM_ADDR_SET_ONE_RX command = (Sensor.COM_ADDR_SET_ONE_RX)MarshalHelper.Deserialize(expCommand, frame.GetRange(3, frame[1] - 2));
Sensor tempSensor = Sensor.GetSensorInstance(command.SerialNumber, command.Address, command.SensorName, command.SensorSubName, command.dataStructType, command.dataStructSubType,command.pcbVersion,command.firmware);
tempSensor.setCommand(command);
SensorContainer.AddSensor(tempSensor);
initalisationFlag = false;
}
else
{
Sensor.COM_ADDR_SET_TO_SN_RX expCommand = new Sensor.COM_ADDR_SET_TO_SN_RX();
Sensor.COM_ADDR_SET_TO_SN_RX command = (Sensor.COM_ADDR_SET_TO_SN_RX)MarshalHelper.Deserialize(expCommand, frame.GetRange(3, frame[1] - 2));
if (command == null)
{
MessageBox.Show("Sensor not answering");
}
else {
Sensor tempSensor = Sensor.GetSensorInstance(command.SerialNumber, command.Address, command.SensorName, command.SensorSubName, command.dataStructType, command.dataStructSubType, command.pcbVersion, command.firmware);
tempSensor.setCommand(command);
SensorContainer.AddSensor(tempSensor);
initalisationFlag = false;
}
}
}
public void OnTimedEvent(object source, ElapsedEventArgs e)
{
framePartPendingFlag = false;
}
}

How to get latitude and longitude in Mono for android?

First i worked with this tutorial tutorial
to get latitude and longitude, but i get nothing, so this is my code :
[Activity(Label = "GetLocation", MainLauncher = true, Icon = "#drawable/icon")]
public class Activity1 : Activity, ILocationListener
{
private Location _currentLocation;
private LocationManager _locationManager;
private TextView _locationText;
private TextView _addressText;
private string _locationProvider;
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();
}
private void InitializeLocationManager()
{
_locationManager = (LocationManager)GetSystemService(LocationService);
var criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
var acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = String.Empty;
}
}
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
private void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
_addressText.Text = "Can't determine the current location.";
return;
}
new Thread(() =>
{
var addressText = "Unable to find a location.";
var geocoder = new Geocoder(this);
var addressList = geocoder.GetFromLocation(_currentLocation.Latitude, _currentLocation.Longitude, 50);
var address = addressList.FirstOrDefault();
if (address != null)
{
var deviceLocation = new StringBuilder();
for (var i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceLocation.Append(address.GetAddressLine(i))
.AppendLine(",");
}
_addressText.Text = deviceLocation.ToString();
}
RunOnUiThread(() => { _addressText.Text = addressText; });
}).Start();
}
public void OnLocationChanged(Location location)
{
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location.";
}
else
{
_locationText.Text = String.Format("{0},{1}", _currentLocation.Latitude, _currentLocation.Longitude);
}
}
public void OnProviderDisabled(string provider) { }
public void OnProviderEnabled(string provider) { }
public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
}
So please if someone has any idea about what wrong with my code i will be very appreciative.
There is one spot in your code where you're updating the the UI _addressText.Text from a background thread. That could also account for why, when you click the button, you're not seeing any address updates. See below for a snippet of the one line of code:
if (address != null)
{
var deviceLocation = new StringBuilder();
for (var i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceLocation.Append(address.GetAddressLine(i))
.AppendLine(",");
}
// Here you were updating the UI thread from the background:
RunOnUiThread(() => _addressText.Text = deviceLocation.ToString());
}

Categories

Resources