I've taken every step described here in Fiddler site for capturing my application (running in emulator) network packets. The strange thing is that I can decode http/https sent from browser but not https packets from my app. It's more interesting that requests get successful responses! Any idea what might be the problem?
I'm completely stocked and have no idea what should I have done which didn't.
First topic, that I've found on Xamarin forum was Why can't Fiddler detect traffic from Xamarin apps?. The answer is to set DefaultWebProxy:
public override void OnCreate()
{
// get IP from fiddler's internet icon at the top right, or via ipconfig for VirtualBox used by Genymotion
WebRequest.DefaultWebProxy = new WebProxy("192.168.56.1", 8888);
base.OnCreate();
...
}
I put it in MainActivity, but it didn't solve my problem.
Which helped me is Debugging HttpClient Calls with fiddler in PCL:
You will need to change your code to use a HttpClientHandler and a proxy
HttpClientHandler handler = new HttpClientHandler ()
{
Proxy = new WebProxy (new Uri("http://[Computer IP]:[Fiddler port number]")),
UseProxy = true
};
using (var client = new HttpClient(handler))
{
// Make your call in here
}
Looks simple enough only PCLs dont include the Web proxy class in its bundled System.Net dll for whatever reason so you will need to write your own by extending the System.Net.IWebProxy interface
like so
public class WebProxy : System.Net.IWebProxy
{
public System.Net.ICredentials Credentials
{
get;
set;
}
private readonly Uri _proxyUri;
public WebProxy(Uri proxyUri)
{
_proxyUri = proxyUri;
}
public Uri GetProxy(Uri destination)
{
return _proxyUri;
}
public bool IsBypassed(Uri host)
{
return false;
}
}
After all this stuff, I was able to capture requests from my Xamarin.Forms app on Android Emulator.
Related
I have trouble with connecting to a local web interface (192.168.10.13:3671) that are connected to my KNX network from the emulator/phone in Android Studio.
I've tried to connect to the same web interface with a already developed app called KNXwizard and that works, but I see in the code that that app uses AsyncTask.
Always getting this error: Error creating KNXnet/IP tunneling link: tuwien.auto.calimero.KNXException: connecting from /192.168.163.198:3671 to /192.168.10.13:3671: socket failed: EPERM (Operation not permitted)
I've checked this posts
Socket failed 1
Socket failed 2
Tried everything there, added permissions to my AndroidManifest.xml, uninstalled, used physical phone etc. But nothing works.
It could be my code, I've tried searching for an alternative method for AsyncTask. So it could be that the code is written wrong. Hope someone could help me out.
MainActivity:
public class MainActivity extends AppCompatActivity {
private static InetSocketAddress local = new InetSocketAddress("192.168.163.198", 3671);
private static InetSocketAddress server = new InetSocketAddress("192.168.10.13",
KNXnetIPConnection.DEFAULT_PORT);
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.button);
ExecutorService executorService = Executors.newSingleThreadExecutor();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executorService.execute(new Runnable() {
#Override
public void run() {
//doInBackground
System.out.println("This example establishes a tunneling connection to the KNXnet/IP server " + server);
// A KNX tunneling link supports NAT (Network Address Translation) if required.
// We also indicate that the KNX installation uses twisted-pair (TP) medium, with TP1 being the most common.
// KNXNetworkLink is the base interface implemented by all supported Calimero links to a KNX network.
try (KNXNetworkLink knxLink = KNXNetworkLinkIP.newTunnelingLink(local, server, false, TPSettings.TP1)) {
System.out.println("Connection established to server " + knxLink.getName());
System.out.println("Close connection again");
} catch (KNXException | InterruptedException e) {
// KNXException: all Calimero-specific checked exceptions are subtypes of KNXException
// InterruptedException: longer tasks that might block are interruptible, e.g., connection procedures. In
// such case, an instance of InterruptedException is thrown.
// If a task got interrupted, Calimero will clean up its internal state and resources accordingly.
// Any deviation of such behavior, e.g., where not feasible, is documented in the Calimero API.
System.out.println("Error creating KNXnet/IP tunneling link: " + e);
}
}
});
}
});
}
I figured it out.
It was a stupid mistake with the IP address, should have seen that before. I just change the IP address to that I have on the phone I was connected to (192.168.10.15).
I connect to the node server with socketio.SocketIO running as a service.And, When Service restarts,opens socket.io without socket.io closure.That's a problem.
A device making multiple socketIO connection on the server side.So the server is swelling..
! I am using gottox/socketio-java-client on android.
Check Socket is connected or not using socket.isConnected().
This will return true if socket is connected
Its just an idea so i don't know the limitations. pls let me know.
You can ping the server to check if the connection is alive.
In android
socket.emit("ping","ping");
socket.on("pong",pingHandler); //EmitterListener
private Emitter.Listener pingHandler=new Emitter.Listener(){
#Override
public void call(final Object... args) {
Log.d("SocketStatus","Connection is active");
});
}
and make the server return response for the ping
socket.on("ping",function(data){
socket.emit("pong","pong"); //from your server ex.Node.js
});
You can check the socket.connected property:
var socket = io.connect();
console.log('Connected status before onConnect', socket.socket.connected);
socket.on('connect', function() {
console.log('Connected status onConnect', socket.socket.connected);
});
It's updated dynamically, if the connection is lost it'll be set to false until the client picks up the connection again. So easy to check for with setInterval or something like that.
Another solution would be to catch disconnect events and track the status yourself.
The following is an expansion/modification of Rafique Mohammed answer above. The correct way is to try to reconnect on client side.
Internet drops (server cannot communicate disconnection to client). Server crashes (server may/may not be able to tell client. Server Restart (server can tell but that just extra work). After reconnection you will also like to rejoin the room for seamless communication
public void connectAfterDisconnectSocket(String senderActivity) {
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
boolean isConnected = false;
isConnected = mSocket != null && mSocket.connected();
if (!isConnected) {
SocketIOClient socketIOClient = new SocketIOClient();
socketIOClient.connectToSocketIO();
if (senderActivity.equals("A")) {
A.joinChatRoom(room);
}
if (senderActivity.equals("B")) {
B.joinChatRoom(room);
}
}
}
}, 0, 1000); //put here time 1000 milliseconds=1 second
}
I am trying to use PortableRest to make an Async call to a Web API 2.2 Rest service from Xamarin Forms.
I think I have some kind of deadlock / synchronisationcontext issue but I cannot work it out (newbie to async etc).
Can anyone please help?
My controller test method (removed any call to database) -
public IEnumerable<ContentModel> GetTestRest()
{
return new List<ContentModel> {
new ContentModel() {Categoryid = 1, Title = "Title"}};
}
My Unit Test Passes -
[TestMethod]
public async Task TestRest()
{
MyNewsApiClient MyNewsApiClient = new MyNewsApiClient();
var models = await MyNewsApiClient.TestRest();
int count = models.Count;
Assert.AreEqual(1, count);
}
My PortableRest Proxy (PCL) Method -
public async Task<List<ContentModel>> TestRest()
{
var request = new RestRequest();
request.Resource = "Content/GetTestRest";
return await ExecuteAsync<List<ContentModel>>(request);
}
Xamarin Forms ContentPage (PCL) -
public partial class NewsType1CP : ContentPage
{
public NewsType1CP ()
{
InitializeComponent ();
}
protected override void OnAppearing ()
{
LoadData (); // this is a sync call of an async method, not sure how else to approach, make OnAppearing async?
}
public async Task LoadData ()
{
Debug.WriteLine ("LoadData");
HeaderLabel.Text = "Load Data!";
MyNewsApiClient api = new MyNewsApiClient ();
var cm = await api.TestRest ();
// this will work on its own, control returns to this method - await api.GetDelay ();
HeaderLabel.Text = "After! - ";
NewsListView.ItemsSource = cm;
}
}
The await to api.TestRest() never results in HeaderLabel.After or ListView being set.
If I just add a test Proxy Method GetDelay() which does not call PortableRest via return await ExecuteAsync>(request);
public async Task<bool> GetDelay ()
{
await Task.Delay (1000);
return true;
}
Then all "works".
Thanks for your help, I will download the source code for PortableRest if required (using Nuget dll at present), just was not sure if missing something basic at this top level.
Right, this eventually has nothing to do with Async (or any Issue with PortableRest), but thought I would share in case it can help others.
I eventually put a try block (obvious next step now!) and caught this exception -
Method not found: 'System.Net.Http.HttpClientHandler.set_AutomaticDecompression'.
So, looking at this -
http://davidburela.wordpress.com/2013/07/12/error-when-using-http-portable-class-library-compression/
PortableRest was already in my Forms PCL, but I needed to add Microsoft Http Client Libraries Nuget to my Android Application.
I then got -
Error: ConnectFailure (The requested address is not valid in this context)
I thought it may be something to do with Android Permissions, but it was not in this case (although I now realise I need to add Internet permission anyway for future calls).
Because I am running my App in a VM (from GenyMotion / Virtual Box) then the Android App cannot access LocalHost (where my Web Api resides)
So, from this -
http://bbowden.tumblr.com/post/58650831283/accessing-a-localhost-server-from-the-genymotion
I can confirm that using the address shown in VirtualBox > File > Preferences > Network > VirtualBox Host-Only Network Adapter > Modify does the job beautifully.
Thanks for your help.
I'm currently attempting to use AppSync to sync a piece of data between an android app and a pebble app. However, I seem to not be able to get the pebble to realize that any data is being transferred - that is, no logs are being produced where they should be. What is really bothering me is that this is essentially the code found in the pebble weather example. I've pasted the relevant bits of code below - could someone possibly look it over and suggest where any issues may be? I've made sure that the UUIDs in both programs (pebble app and android app) are the same, and that they are on the same network, and that the pebble is actually connected to the phone, and that the android function is actually being called and all.
Snippet of pebble app code:
static void sync_error_callback(DictionaryResult dict_error, AppMessageResult app_message_error, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "App Message Sync Error: %d", app_message_error);
}
static void sync_tuple_changed_callback(const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, new_tuple->value->cstring);
}
void home_screen_load() {
// set up each one of the SimpleMenuItems
Tuplet initial_values[] = {
TupletCString(0x0, "Initial 1")
};
app_sync_init(&sync, sync_buffer, sizeof(sync_buffer), initial_values, ARRAY_LENGTH(initial_values), sync_tuple_changed_callback, sync_error_callback, NULL);
}
Snippet of android app:
final UUID PEBBLE_APP_UUID = UUID.fromString("10549fd4-1fe4-4d30-8a18-6f2f8149f8fd");
public void sendDataToWatch(String toSend) {
// Build up a Pebble dictionary containing the weather icon and the current temperature in degrees celsius
PebbleDictionary data = new PebbleDictionary();
data.addString(0x0, toSend);
PebbleKit.sendDataToPebble(getApplicationContext(), PEBBLE_APP_UUID, data);
}
To debug this type of problem, you should set a inbox_dropped handler and see if you get anything there.
After initializing AppMessage and AppSync, call:
app_message_register_inbox_dropped(appmsg_in_dropped);
And add this function:
static void appmsg_in_dropped(AppMessageResult reason, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "In dropped: %s", translate_error(reason));
}
Take a look at this question for the source of the translate_error function.
I have a GoPro Hero3 Black Edition and after reading their user forums, I got these 2 url commands that can control the shutter button while the GoPro is acting as a hotspot.
Record/shoot Command
On http://10.5.5.9:80/bacpac/SH?t=WIFIPASSWORD&p=%01
Off http://10.5.5.9:80/bacpac/SH?t=WIFIPASSWORD&p=%00
I have tried using the URLs in my Nexus 7's Chrome Browser but I want to integrate these 2 commands in a button in my Android app when my Nexus 7 connects via wifi to the GoPro.
How do I do this? Thanks in advance.
It's not that tough. Create an activity class and a couple of buttons to fire the HTTP commands.
Keep in mind that these are network calls and have to be made from a separate background thread (not the main thread).
btnToggle.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Toggle the camera power
new OperateCamera().execute();
}
});
Create a new AsyncTask class:
class OperateCamera extends AsyncTask<String, Void, Boolean> {
protected Boolean doInBackground(String... urls) {
return triggerShutter();
}
// Method to trigger the shutter
boolean triggerShutter(){
try {
// Make network call
return true;
}
catch (Exception e) {
return false;
}
}
}
Just use the legacy URLConnection or some lib like OkHttp to access these urls and trigger the shutter. I'd recommend the second ;)