I am trying to convert a users input in Edit text to LatLng when the Search button is clicked. This will then update the camera and move tot hat position.
Here is my code in the main:
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Gms.Maps;
using Android.Views;
using Android.Gms.Maps.Model;
using System.Collections.Generic;
using Android.Locations;
using System.Linq;
namespace SafeandSound
{
[Activity(Label = "SafeandSound", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
private GoogleMap mMap;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
SetUpMap();
}
private void SetUpMap()
{
if (mMap == null)
{
FragmentManager.FindFragmentById<MapFragment>(Resource.Id.map);
}
}
public void OnMapReady(GoogleMap googleMap)
{
mMap = googleMap;
}
// Button to Search for Address//
public void onMapSearch(View view)
{
EditText address = (EditText)FindViewById(Resource.Id.searchText);
var addressnew = address.Text;
if (addressnew != null)
{
addressnew = address.Text;
}
Geocoder geoCoder = new Geocoder(this);
IList<Address> coordinates = geoCoder.GetFromLocationName(addressnew, 0);
Address gotAddress = coordinates.FirstOrDefault();
LatLng latLng = new LatLng(gotAddress.Latitude, gotAddress.Longitude);
CameraPosition.Builder builder = CameraPosition.InvokeBuilder();
builder.Target(latLng);
builder.Zoom(10);
CameraPosition cameraPosition = builder.Build();
CameraUpdate cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);
}
}
}
When I use this right now, I get an exception error. Please HELP!!!
First you need to check if the Geocoder service is available on the device/emulator via the static method:
Geocoder.isPresent
Note: The use of Geocoder requires Internet access and Google Play services to be installed...
Next you are requesting zero results in the "maxResults" parameter:
GetFromLocationName(addressnew, 0);
int: max number of results to return. Smaller numbers (1 to 5) are recommended
Also you might need to retry the request to obtain results. You should not hammer the service as you will get throttled. Use a retry delay that increasing after each attempt.
Example:
if (!Geocoder.IsPresent)
{
Log.Error("SO", "Geocoder is not present");
}
else
{
var geocoder = new Geocoder(this);
var retry = 0;
do
{
var addressList = await geocoder.GetFromLocationNameAsync("Starbucks 523 Pine Street, Seattle, WA, 98101", 5);
if (addressList.Count > 0)
{
foreach (var address in addressList)
{
Log.Debug("SO", $"{address.Latitude}:{address.Longitude} - {address.FeatureName} : {address.GetAddressLine(0)} : {address.GetAddressLine(1)}");
}
break;
}
retry++;
Log.Warn("SO", $"No addresses returned...., retrying in {retry * 2} secs");
await Task.Delay(retry * 1000);
} while (retry < 5);
}
Output:
[SO] 47.611423:-122.337519 - Starbucks : Starbucks : 400 Pine Street
[SO] 47.611848:-122.335693 - Starbucks : Starbucks : 515 Pine Street
Related
I'm using an open-source game to write a script, that captures the screen frames in a collection and sends the collection to an API server.
Capturing works fine, but as soon as the API request fires, the game freezes for ~500ms. If I understand correctly, this request blocks the main thread.
I've tried to send the request in a different thread, but get some weird errors.
How can I send requests in a background, so it doesn't block the main thread?
Here's my code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using System.Threading.Tasks;
public class Recorder : MonoBehaviour
{
private float captureInterval = 1f / 24f;
private readonly List<string> frames = new();
async void Update()
{
if (Time.timeSinceLevelLoad >= captureInterval)
{
StartCoroutine(CaptureFrame());
captureInterval = Time.timeSinceLevelLoad + (1f / 24f);
if (frames.Count >= 120)
{
StartCoroutine(CommitFrames(frames));
frames.Clear();
}
}
}
IEnumerator CaptureFrame()
{
yield return new WaitForEndOfFrame();
Texture2D texture = ScreenCapture.CaptureScreenshotAsTexture();
byte[] jpg = texture.EncodeToJPG();
string base64 = Convert.ToBase64String(jpg);
frames.Add(base64);
Destroy(texture);
}
IEnumerator CommitFrames(List<string> framesData)
{
var payload = new CommitFramesData() { frames = framesData };
var www = CreateRequest("http://my-api.test/api/frames", RequestType.POST, payload);
yield return www.SendWebRequest();
www.Dispose();
}
private UnityWebRequest CreateRequest(string path, RequestType type = RequestType.GET, object data = null)
{
var request = new UnityWebRequest(path, type.ToString());
if (data != null)
{
var bodyRaw = Encoding.UTF8.GetBytes(JsonUtility.ToJson(data));
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
}
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
return request;
}
}
public enum RequestType
{
GET = 0,
POST = 1,
PUT = 2
}
[Serializable]
class CommitFramesData
{
public List<string> frames;
}
This question already has answers here:
PreferenceManager getDefaultSharedPreferences deprecated in Android Q
(9 answers)
Closed 8 months ago.
I recently updated the nugget packages in my Android project and now I get a message in this line of code:
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context);
CS0618: PreferenceManager.GetDefaultSharedPreferences(Context?) is obsolete: deprecated
enter image description here
Is it necessary to change something? Will my code not work correctly like this? Should I completely remove private void storeToken(String token)? I'm not sure if I still need private void storeToken(String token).
using System;
using Android.App;
using Android.Content;
using Android.Util;
using Firebase.Messaging;
using System.Collections.Generic;
using Android.Preferences;
using Android.Media;
using AndroidX.Core.App;
namespace AndroidVersion
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirebaseMsgService";
public override void OnNewToken(string token)
{
Log.Debug(TAG, "Refreshed token: " + token);
storeToken(token);
}
private void storeToken(String token)
{
//saving the token on shared preferences
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context);
ISharedPreferencesEditor editor = prefs.Edit();
editor.PutString("my_token", token);
editor.Apply();
}
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(TAG, "From: " + message.From);
var body = message.GetNotification().Body;
var title = message.GetNotification().Title;
Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
SendNotification(body, title, message.Data);
}
void SendNotification(string messageBody, string Title, IDictionary<string, string> data)
{
var intent = new Intent(this, typeof(Activity1));
intent.AddFlags(ActivityFlags.ClearTop);
foreach (var key in data.Keys)
{
intent.PutExtra(key, data[key]);
}
var pendingIntent = PendingIntent.GetActivity(this,
Activity1.NOTIFICATION_ID,
intent,
PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(this, Activity1.CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.Icon)
.SetContentTitle(Title)
.SetContentText(messageBody)
.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
.SetVibrate(new long[] { 1000, 1000, 0, 0, 0 })
.SetLights(Android.Graphics.Color.Red, 3000, 3000)
.SetPriority((int)NotificationPriority.High)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(Activity1.NOTIFICATION_ID, notificationBuilder.Build());
}
}
}
I use implementation 'androidx.preference:preference-ktx:1.1.1'
successfully replaced the deprecated android.preference.PreferenceManager in my project
Use using AndroidX.Preference; instead of using Android.Preferences;
I'm trying to find a working sample to record videos with IOS (using xamarin) but there's always something missing or not working for me.
My best try using several forum posts and samples is the following :
using System;
using CoreGraphics;
using Foundation;
using UIKit;
using AVFoundation;
using CoreVideo;
using CoreMedia;
using CoreFoundation;
using System.IO;
using AssetsLibrary;
namespace avcaptureframes {
public partial class AppDelegate : UIApplicationDelegate {
public static UIImageView ImageView;
UIViewController vc;
AVCaptureSession session;
OutputRecorder outputRecorder;
DispatchQueue queue;
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
ImageView = new UIImageView (new CGRect (10f, 10f, 200f, 200f));
ImageView.ContentMode = UIViewContentMode.Top;
vc = new UIViewController {
View = ImageView
};
window.RootViewController = vc;
window.MakeKeyAndVisible ();
window.BackgroundColor = UIColor.Black;
if (!SetupCaptureSession ())
window.AddSubview (new UILabel (new CGRect (20f, 20f, 200f, 60f)) {
Text = "No input device"
});
return true;
}
bool SetupCaptureSession ()
{
// configure the capture session for low resolution, change this if your code
// can cope with more data or volume
session = new AVCaptureSession {
SessionPreset = AVCaptureSession.PresetMedium
};
// create a device input and attach it to the session
var captureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);
if (captureDevice == null) {
Console.WriteLine ("No captureDevice - this won't work on the simulator, try a physical device");
return false;
}
//Configure for 15 FPS. Note use of LockForConigfuration()/UnlockForConfiguration()
NSError error = null;
captureDevice.LockForConfiguration (out error);
if (error != null) {
Console.WriteLine (error);
captureDevice.UnlockForConfiguration ();
return false;
}
if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0))
captureDevice.ActiveVideoMinFrameDuration = new CMTime (1, 15);
captureDevice.UnlockForConfiguration ();
var input = AVCaptureDeviceInput.FromDevice (captureDevice);
if (input == null) {
Console.WriteLine ("No input - this won't work on the simulator, try a physical device");
return false;
}
session.AddInput (input);
// create a VideoDataOutput and add it to the sesion
var settings = new CVPixelBufferAttributes {
PixelFormatType = CVPixelFormatType.CV32BGRA
};
using (var output = new AVCaptureVideoDataOutput { WeakVideoSettings = settings.Dictionary }) {
queue = new DispatchQueue ("myQueue");
outputRecorder = new OutputRecorder ();
output.SetSampleBufferDelegate (outputRecorder, queue);
session.AddOutput (output);
}
session.StartRunning ();
return true;
}
public override void OnActivated (UIApplication application)
{
}
public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate
{
AVAssetWriter writer=null;
AVAssetWriterInput writerinput= null;
CMTime lastSampleTime;
int frame=0;
NSUrl url;
public OutputRecorder()
{
string tempFile = Path.Combine(Path.GetTempPath(), "NewVideo.mp4");
if (File.Exists(tempFile)) File.Delete(tempFile);
url = NSUrl.FromFilename(tempFile);
NSError assetWriterError;
writer = new AVAssetWriter(url, AVFileType.Mpeg4, out assetWriterError);
var outputSettings = new AVVideoSettingsCompressed()
{
Height = 300,
Width = 300,
Codec = AVVideoCodec.H264,
CodecSettings = new AVVideoCodecSettings
{
AverageBitRate = 1000000
}
};
writerinput = new AVAssetWriterInput(mediaType: AVMediaType.Video, outputSettings: outputSettings);
writerinput.ExpectsMediaDataInRealTime = false;
writer.AddInput(writerinput);
}
public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
{
try
{
lastSampleTime = sampleBuffer.PresentationTimeStamp;
var image = ImageFromSampleBuffer(sampleBuffer);
if (frame == 0)
{
writer.StartWriting();
writer.StartSessionAtSourceTime(lastSampleTime);
frame = 1;
}
String infoString = "";
if (writerinput.ReadyForMoreMediaData)
{
if (!writerinput.AppendSampleBuffer(sampleBuffer))
{
infoString = "Failed to append sample buffer";
}
else
{
infoString = String.Format("{0} frames captured", frame++);
}
}
else
{
infoString = "Writer not ready";
}
Console.WriteLine(infoString);
ImageView.BeginInvokeOnMainThread(() => ImageView.Image = image);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
sampleBuffer.Dispose();
}
}
UIImage ImageFromSampleBuffer (CMSampleBuffer sampleBuffer)
{
// Get the CoreVideo image
using (var pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer)
{
// Lock the base address
pixelBuffer.Lock (CVOptionFlags.None);
// Get the number of bytes per row for the pixel buffer
var baseAddress = pixelBuffer.BaseAddress;
var bytesPerRow = (int)pixelBuffer.BytesPerRow;
var width = (int)pixelBuffer.Width;
var height = (int)pixelBuffer.Height;
var flags = CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Little;
// Create a CGImage on the RGB colorspace from the configured parameter above
using (var cs = CGColorSpace.CreateDeviceRGB ())
{
using (var context = new CGBitmapContext (baseAddress, width, height, 8, bytesPerRow, cs, (CGImageAlphaInfo)flags))
{
using (CGImage cgImage = context.ToImage ())
{
pixelBuffer.Unlock (CVOptionFlags.None);
return UIImage.FromImage (cgImage);
}
}
}
}
}
void TryDispose (IDisposable obj)
{
if (obj != null)
obj.Dispose ();
}
}
}
}
This works displaying live camera image and I get "frames captured" message in consol but I don't find how to record to file.
I read somewhere about adding VideoCapture but I don't know how to link with my code.
Any help will is welcome.
From your code, in the construct of class OutputRecorder you have defined the url where you want to save the recording:
string tempFile = Path.Combine(Path.GetTempPath(), "NewVideo.mp4");
if (File.Exists(tempFile)) File.Delete(tempFile);
url = NSUrl.FromFilename(tempFile);
It means you want to save the video in the tmp folder in the app's sandbox. If you want to use the video sometime later, I recommend you to change the folder to documents by using:
string filePath = Path.Combine(NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User)[0], "NewVideo.mp4");
I notice that you have called session.StartRunning(); in the method bool SetupCaptureSession() to start recording. please add session.StopRunning(); to end recording then the video will be saved in the path we just defined above.
Moreover, you can retrieve the video with the path like:
NSData videoData = NSData.FromFile(filePath);
I'm beginner with C#. I've wrote a very simple Console project to get location coordinates on my PC.
using LocationProvider;
using System;
using System.Threading.Tasks;
namespace TestLocationProvider
{
class Program
{
static void Main(string[] args)
{
obtenerPosicion();
Console.ReadKey();
}
public async static void obtenerPosicion()
{
GPSAccess gps = new GPSAccess();
Task<GPSData> longRunningTask = gps.GetCurrentPosition();
GPSData result = await longRunningTask;
Console.WriteLine(result);
}
}
}
The LocationProvider namespace is as follows:
using System;
using System.Threading.Tasks;
using Windows.Devices.Geolocation;
namespace LocationProvider
{
public class GPSAccess
{
public async Task<GPSData> GetCurrentPosition()
{
GPSData data;
Geolocator loc = new Geolocator();
try
{
data = new GPSData();
loc.DesiredAccuracy = PositionAccuracy.High;
Geoposition pos = await loc.GetGeopositionAsync();
var lat = pos.Coordinate.Point.Position.Latitude;
var lang = pos.Coordinate.Point.Position.Longitude;
data.latitud = Math.Truncate(lat) * 100 + (lat - Math.Truncate(lat)) * 60;
data.longitud = Math.Truncate(lang) * 100 + (lang - Math.Truncate(lang)) * 60;
return data;
}
catch (System.UnauthorizedAccessException)
{
// handle error
}
return null;
}
}
}
Im using references for Windows 8.1
- Windows.Devices
- Windows.Foundations
and .NET 4.5
- System.Threading.Tasks
However Im getting an error on the line
Geoposition pos = await loc.GetGeopositionAsync();
that says:
IAsyncOperation<Geoposition> does not contain a definition for
GetAwaiter and not extension method GetAwaiter accepting a first
argument of type IAsyncOperation<Geoposition> could be found (are
you missing a using directive for System?)
Am I forgetting some reference?
I am trying for my school to use the Bing Map API and use GeocodeAdress. I build this application: http://msdn.microsoft.com/en-us/library/dd221354.aspx and the problem is I get this error every time.
it is at line 62: this method: GeocodeServiceClient geocodeService = new GeocodeServiceClient();
!InvalidOperationException was unhandled
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
Additional information: An endpoint configuration section for contract 'GeocodeService.IGeocodeService' could not be loaded because more than one endpoint configuration for that contract was found. Please indicate the preferred endpoint configuration section by name.
Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BingMapsSample.GeocodeService;
using BingMapsSample.SearchService;
using BingMapsSample.ImageryService;
using BingMapsSample.RouteService;
namespace BingMapsSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private String GeocodeAddress(string address)
{
string results = "";
string key = "Validate Bing Map Education Code";
GeocodeRequest geocodeRequest = new GeocodeRequest();
// Set the credentials using a valid Bing Maps key
geocodeRequest.Credentials = new GeocodeService.Credentials();
geocodeRequest.Credentials.ApplicationId = key;
// Set the full address query
geocodeRequest.Query = address;
// Set the options to only return high confidence results
ConfidenceFilter[] filters = new ConfidenceFilter[1];
filters[0] = new ConfidenceFilter();
filters[0].MinimumConfidence = GeocodeService.Confidence.High;
// Add the filters to the options
GeocodeOptions geocodeOptions = new GeocodeOptions();
geocodeOptions.Filters = filters;
geocodeRequest.Options = geocodeOptions;
// Make the geocode request
GeocodeServiceClient geocodeService = new GeocodeServiceClient();
GeocodeResponse geocodeResponse = geocodeService.Geocode(geocodeRequest);
if (geocodeResponse.Results.Length > 0)
results = String.Format("Latitude: {0}\nLongitude: {1}",
geocodeResponse.Results[0].Locations[0].Latitude,
geocodeResponse.Results[0].Locations[0].Longitude);
else
results = "No Results Found";
return results;
}
private string ReverseGeocodePoint(string locationString)
{
string results = "";
string key = "Validate Bing Map Education Code";
ReverseGeocodeRequest reverseGeocodeRequest = new ReverseGeocodeRequest();
// Set the credentials using a valid Bing Maps key
reverseGeocodeRequest.Credentials = new GeocodeService.Credentials();
reverseGeocodeRequest.Credentials.ApplicationId = key;
// Set the point to use to find a matching address
GeocodeService.Location point = new GeocodeService.Location();
string[] digits = locationString.Split(',');
point.Latitude = double.Parse(digits[0].Trim());
point.Longitude = double.Parse(digits[1].Trim());
reverseGeocodeRequest.Location = point;
// Make the reverse geocode request
GeocodeServiceClient geocodeService = new GeocodeServiceClient();
GeocodeResponse geocodeResponse = geocodeService.ReverseGeocode(reverseGeocodeRequest);
if (geocodeResponse.Results.Length > 0)
results = geocodeResponse.Results[0].DisplayName;
else
results = "No Results found";
return results;
}
private string SearchKeywordLocation(string keywordLocation)
{
String results = "";
String key = "Validate Bing Map Education Code";
SearchRequest searchRequest = new SearchRequest();
// Set the credentials using a valid Bing Maps key
searchRequest.Credentials = new SearchService.Credentials();
searchRequest.Credentials.ApplicationId = key;
//Create the search query
StructuredSearchQuery ssQuery = new StructuredSearchQuery();
string[] parts = keywordLocation.Split(';');
ssQuery.Keyword = parts[0];
ssQuery.Location = parts[1];
searchRequest.StructuredQuery = ssQuery;
//Define options on the search
searchRequest.SearchOptions = new SearchOptions();
searchRequest.SearchOptions.Filters =
new FilterExpression()
{
PropertyId = 3,
CompareOperator = CompareOperator.GreaterThanOrEquals,
FilterValue = 8.16
};
//Make the search request
SearchServiceClient searchService = new SearchServiceClient();
SearchResponse searchResponse = searchService.Search(searchRequest);
//Parse and format results
if (searchResponse.ResultSets[0].Results.Length > 0)
{
StringBuilder resultList = new StringBuilder("");
for (int i = 0; i < searchResponse.ResultSets[0].Results.Length; i++)
{
resultList.Append(String.Format("{0}. {1}\n", i + 1,
searchResponse.ResultSets[0].Results[i].Name));
}
results = resultList.ToString();
}
else
results = "No results found";
return results;
}
private void Geocode_Click(object sender, RoutedEventArgs e)
{
labelResults.Content = GeocodeAddress(textInput.Text);
}
private void ReverseGeocode_Click(object sender, RoutedEventArgs e)
{
labelResults.Content = ReverseGeocodePoint(textInput.Text);
}
private void Search_Click(object sender, RoutedEventArgs e)
{
labelResults.Content = SearchKeywordLocation(textInput.Text);
}
}
}
I found the solution line 62 should be:
var geocodeService = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
Open your web.config file or app.config file. In there you will see a basic and custom binding configuration for the service. Remove the custom binding section. Clean and build your project and it should work.
As a side note. The Bing Maps SOAP services are really old and limited in functionality. They were released about 8 years ago. A newer REST based service was released about 4 years ago. REST is faster, has smaller response packages and has more features. You can find out more about the Bing Maps REST services here: http://msdn.microsoft.com/en-us/library/ff701713.aspx