What would be best way to measure data usage in Android Xamarin app in Visual Studio?
I would like to know, how much data was transferred for each called request.
I was looking in Xamarin Profiler but there isn't any info about data usage.
Thanks.
One approach that you could use is via Android Device Monitor to watch network traffic
Alternatively you could wrap your request if you are using HttpClient in a custom handler and log the size of the request payload:
public class RequestLoggerHandler : HttpClientHandler
{
#if DEBUG
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var stopwatch = Stopwatch.StartNew();
HttpResponseMessage response = null;
var headers = request.Headers;
var responseString = string.Empty;
var requestString = string.Empty;
var outputStringBuilder = new StringBuilder();
const string LINE_ENDING = "===================================================================================================";
const string SECTION_ENDING = "---------------------------------------------------------------------------------------------------";
try
{
if (request.Content != null) requestString = await request.Content?.ReadAsStringAsync();
response = await base.SendAsync(request, cancellationToken);
responseString = await response.Content?.ReadAsStringAsync();
outputStringBuilder.AppendLine(LINE_ENDING);
// Headers
outputStringBuilder.AppendLine("REQUEST HEADERS:");
foreach (var header in headers)
outputStringBuilder.AppendLine($"HEADER: {header.Key}: {header.Value?.ToList()?.FirstOrDefault()}");
outputStringBuilder.AppendLine(SECTION_ENDING);
// Parameters
outputStringBuilder.AppendLine("REQUEST PARAMS:");
outputStringBuilder.AppendLine(requestString);
outputStringBuilder.AppendLine(SECTION_ENDING);
// Response
outputStringBuilder.AppendLine("RESPONSE:");
outputStringBuilder.AppendLine(responseString);
outputStringBuilder.AppendLine(SECTION_ENDING);
return response;
}
finally
{
stopwatch.Stop();
var totalSize = 0L;
if (response != null)
{
var bodylength = response.Content.Headers.ContentLength;
var headerlength = response.Headers.ToString().Length;
totalSize = bodylength.GetValueOrDefault() + headerlength;
}
outputStringBuilder.AppendLine(string.Format("REQUEST [{0}:{1}] Time:{2}| Size:{3}| HTTP-CODE:{4}",
request.Method.ToString(),
request.RequestUri,
stopwatch.Elapsed.ToString("ss\\.fff"),
totalSize.ToPrettyByteSize(),
response?.StatusCode.ToString() ?? "No Internet Connectivity"));
outputStringBuilder.AppendLine(LINE_ENDING);
Debug.WriteLine("\n" + outputStringBuilder);
}
}
#endif
}
Then in your output window using VSColorOutput extension it produces a nice readable report of your request/response, including time and size. You can of cause simplify this code if all you are after is just the request/response size.
Related
I am using stripe to process my payments. I noticed that it keeps charging only $14.00 and I wanted to know how can I change that to something $1.00. I tried modifying the app.post("create-payment-intent") and still nothing is changing. Every time I check my stripe dashboard I still see $14.00 being charged. I have a copy of my code. Can someone please assist me with this. Thanks in advance
//Code
private void startCheckout() {
//amount will calculate from .00 make sure multiply by 100
//double amount=Double.parseDouble(mAmount.getText().toString())*1;
// Create a PaymentIntent by calling the sample server's /create-payment-intent endpoint.
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
/*
String json = "{"
+ "\"currency\":\"usd\","
+ "\"items\":["
+ "{\"id\":\"photo_subscription\"}"
+ "]"
+ "}";
*/
double amount=123.0;
Map<String,Object> payMap=new HashMap<>();
Map<String,Object> itemMap=new HashMap<>();
List<Map<String,Object>> itemList =new ArrayList<>();
payMap.put("currency","usd");
payMap.put("amount","amount");
itemMap.put("id","photo_subscription");
itemMap.put("amount",amount);
itemList.add(itemMap);
payMap.put("items",itemList);
String json = new Gson().toJson(payMap);
//Log.i("TAG", "startCheckout: "+json);
RequestBody body = RequestBody.create(mediaType,json);
Request request = new Request.Builder()
.url(BACKEND_URL + "create-payment-intent")
.post(body)
.build();
httpClient.newCall(request)
.enqueue(new PayCallback(this));
// Hook up the pay button to the card widget and stripe instance
//Button payButton = findViewById(R.id.payButton);
payButton.setOnClickListener((View view) -> {
//String get_card=cardInputWidget.getCard().getAddressZip();
//Toast.makeText(PaymentPageActivity.this, get_card, Toast.LENGTH_SHORT).show();
PaymentMethodCreateParams params = cardInputWidget.getPaymentMethodCreateParams();
if (params != null) {
Map<String, String> extraParams = new HashMap<>();
extraParams.put("setup_future_usage", "off_session");
ConfirmPaymentIntentParams confirmParams = ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(params, paymentIntentClientSecret);
stripe.confirmPayment(this, confirmParams);
}
});
}
//server.js
const express = require("express");
const app = express();
const { resolve } = require("path");
// This is your real test secret API key.
const stripe = require("stripe")("sk_test_****************");
app.use(express.static("."));
app.use(express.json());
const calculateOrderAmount = items => {
// Replace this constant with a calculation of the order's amount
// Calculate the order total on the server to prevent
// people from directly manipulating the amount on the client
return 100;
};
app.post("/create-payment-intent", async (req, res) => {
const { items } = req.body;
// Create a PaymentIntent with the order amount and currency
const paymentIntent = await stripe.paymentIntents.create({
amount: calculateOrderAmount(items),
currency: "usd"
});
res.send({
clientSecret: paymentIntent.client_secret
});
});
app.get("/greet", async (req, res) => {
res.send('hello it is working');
});
const PORT= process.env.PORT || 5001;
app.listen(PORT, () => console.log('Node server listening on port $(PORT)'));
The issue here is that your client code is pointing to a server that does not have your local changes. You have two options:
Change your BACKEND_URL to point to your local server while your testing
Leave your BACKEND_URL as is, commit and push your changes to master, and run git push heroku master to push your changes to heroku.
I have a problem with my app in Xamarin Forms.
The GET request works in debug mode but not in release mode.
The POST request works in both mode.
I test on real device and emulator Android.
The api path is HTTPS and the app has INTERNET permission.
This is the code:
if (IsConnected)
{
string jsonRequest = JsonConvert.SerializeObject(request);
StringContent content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
var Request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(client.BaseAddress + $"api/Servizi/getServizi"),
Content = content
};
var jsonResponse = await client.SendAsync(Request);//.ConfigureAwait(false);
var contents = await jsonResponse.Content.ReadAsStringAsync();
response = await Task.Run(() => JsonConvert.DeserializeObject<ServiziResponse>(contents));
}
In visual Studio Add this line in Android Options
VS19
I'm developing a video application with HLS streams.
These streams can only be played if I send in the request https custom headers.
On iOS I do like this:
NSMutableDictionary* headers = [NSMutableDictionary dictionary];
[headers setObject:#"MY_VALUE" forKey:#"MY_KEY"];
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:videoTempURL options:#{#"AVURLAssetHTTPHeaderFieldsKey": headers}];
AVPlayerItem *myNewitem = [[AVPlayerItem alloc] initWithAsset:asset];
and on android like this:
DefaultHttpDataSource.Factory MGSource = new DefaultHttpDataSourceFactory(Util.getUserAgent( MainActivity.getContext(), "MY_USER_AGENT"), BANDWIDTH_METER);
MGSource.getDefaultRequestProperties().set("MY_KEY", "MY_VALUE");
and these methods work very well.
And I want to send these feeds on a ChromeCast.
So I look at how to do on Google Doc and they say this in receiver :
in this function :
sampleplayer.CastPlayer.prototype.loadVideo_ = function(info) {
this.log_('loadVideo_');
var self = this;
var protocolFunc = null;
var url = info.message.media.contentId;
...
host.updateSegmentRequestInfo = function(requestInfo) {
// example of setting CORS withCredentials
requestInfo.withCredentials = true;
// example of setting headers
//requestInfo.headers = {};
//requestInfo.headers['content-type'] = 'text/xml;charset=utf-8';
requestInfo.headers['MY_KEY'] = 'MY_VALUE';
console.log("################# SENDING HEADERS");
};
host.updateManifestRequestInfo = function(requestInfo) {
if (!requestInfo.url) {
requestInfo.url = this.url;
}
requestInfo.withCredentials = true;
};
host.updateLicenseRequestInfo = function(requestInfo) {
requestInfo.withCredentials = true;
};
But that does not work, can someone tell me how I can send custom headers in a URL to a ChromeCast.
Either in the Android sender or in the receiver.
thank you so much
How do I set the CORS headers for M3U8 file streaming in Chromecast? In my sender (Android) I am setting the Metadata and MediaInfo like this:
metaData = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
metaData.putString(MediaMetadata.KEY_TITLE, "Demo Video");
MediaInfo mediaInfo = new MediaInfo.Builder(
"http://playertest.longtailvideo.com/adaptive/bbbfull/bbbfull.m3u8")
.setContentType("application/vnd.apple.mpegurl")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(metaData)
.build();
player.load(client, mediaInfo, true)
.setResultCallback(new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
#Override
public void onResult(RemoteMediaPlayer.MediaChannelResult mediaChannelResult) {
Status status = mediaChannelResult.getStatus();
if (status.isSuccess()) {
}
}
});
My onLoad method is set up like this:
mediaManager.onLoad = function(event) {
console.log("### Media Manager - LOAD: " + JSON.stringify(event));
if(mediaPlayer !== null) {
mediaPlayer.unload(); // Ensure unload before loading again
}
if (event.data['media'] && event.data['media']['contentId']) {
var url = event.data['media']['contentId'];
mediaHost = new cast.player.api.Host({
'mediaElement': mediaElement,
'url': url
});
mediaHost.onError = function (errorCode) {
console.error('### HOST ERROR - Fatal Error: code = ' + errorCode);
if (mediaPlayer !== null) {
mediaPlayer.unload();
}
}
var initialTimeIndexSeconds = event.data['media']['currentTime'] || 0;
// TODO: real code would know what content it was going to access and this would not be here.
var protocol = null;
var parser = document.createElement('a');
parser.href = url;
var ext = ext = parser.pathname.split('.').pop();
if (ext === 'm3u8') {
protocol = cast.player.api.CreateHlsStreamingProtocol(mediaHost);
} else if (ext === 'mpd') {
protocol = cast.player.api.CreateDashStreamingProtocol(mediaHost);
} else if (ext === 'ism/') {
protocol = cast.player.api.CreateSmoothStreamingProtocol(mediaHost);
}
console.log('### Media Protocol Identified as ' + ext);
if (protocol === null) {
mediaManager['onLoadOrig'](event); // Call on the original callback
} else {
mediaPlayer = new cast.player.api.Player(mediaHost);
mediaPlayer.load(protocol, initialTimeIndexSeconds);
}
}
}
However, I am getting this error:
XMLHttpRequest cannot load http://playertest.longtailvideo.com/adaptive/bbbfull/bbbfull.m3u8. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '----' is therefore not allowed access.
For Chromecast, how do I set the CORS headers for Chromecast?
Probably too late, but just came across with the same issue and get it done by the approach mentioned below.
I didn't get a way to add headers on sender app side so, sharing my own experience. I get the CORS issue fixed upon firstly confirming that my server is supporting CORS. And then for playing the media on chromecast, i was needed to add gstatic.com and in my case another one as well as allowed domains on server, which is in-fact the whole idea of CORS, that each domain should be known to our server. And that's it.
Note: Be very much sure to go through this official documentation. But for being a beginner it may appear a bit tricky to grab all the stuff from here. So shared own experience as well.
How to display JSON coming from php in intel App Framwork app. I have tried .getJSON() and .getJSONP() methods. Is there any full guide explaining these methods and how to use them?
Here are documentations for $.getJSON() and $.jsonP()
found the answer .
function getRaceData() {
var postBody = "";
postBody = "rid="+theRID;
var parameters = new AppMobi.Device.RemoteDataParameters();
parameters.url = "http://MyWebSite.com/php_src/getRaceData.php";
parameters.id = "1007";
parameters.method = "POST";
parameters.body = postBody;
jq.ui.showMask('loading race data');
AppMobi.device.getRemoteDataExt(parameters);
}
//then somewhere in your event handler, check the ID of the response and process the JSON....
case 1007: //got race data
var raceData = jq.parseJSON(event.response);
jq("#raceRCList").hide();
jq("#raceRCname").html(raceData.race_name);
jq("#raceRCdate").val(raceData.date);
jq("#raceRCstart").val(raceData.start_time);
jq("#raceRCData").show();
break;