I have been trying to implement ModernHttpClient as explained here: http://motzcod.es/post/78863496592/portable-class-libraries-httpclient-so-happy
the main problem is I cannot get it to recognise OkHttpNetworkHandler for Android or AFNetworkHandler for iOS - I don't know the using references for each. For Android I have System.Net.Http, ModernHttpClient and OKHttp. for iOS System.Net.Htp and ModernHttpClient. I have searched but cannot even find sample code that includes the usings
public class HttpClientHelper : IHttpClientHelper
{
private HttpMessageHandler handler;
public HttpMessageHandler MessageHandler
{
get { return handler ?? (handler = new OkHttpNetworkHandler()); }
}
}
public class HttpClientHelper : IHttpClientHelper
{
private HttpMessageHandler handler;
public HttpMessageHandler MessageHandler
{
get { return handler ?? (handler = new AFNetworkHandler()); }
}
}
Okay, seems you don't need any of that
Add the ModernHttpClient as a NuGet package to the PCL and then all you need to do is this
HttpClient client = new HttpClient(new NativeMessageHandler());
Works, and heaps faster than just HttpClient
Related
I am not sure of the terminology for what I'm looking to do, so sorry in advance!
I've found a FilePicker plugin for Xamarin.Forms (https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows) that implements device-specific functionality for selecting files via the CrossFilePicker class.
The way to use leverage this functionality would be something like
CrossFilePicker.Current.OpenFile("Filename.txt");
The most important part of this for me is that CrossFilePicker.Current is static and can be accessible from anywhere in the shared layer of my Xamarin.Forms app.
I need to implement a class with the same characteristics. I want to leverage device Accessibility functionality (i.e. determining if a screen reader is enabled) and I need to be able to do so with a static class.
My eventual plan is to then wrap this static class so that I can use it for unit tests too.
I don't want to import device libraries into my shared project.
TLDR: I need a static class that implements device-specific functionality.
Any help would be greatly appreciated! Thank you :)
EDIT:
Here are the files I have currently implemented in my project
IAccessibilityService Located in the shared .NET project
namespace Bitspace.Services
{
public interface IAccessibilityService
{
public bool IsScreenReaderEnabled();
public void Announcement(string message);
public void NavigationAnnouncement(string message);
}
}
DeviceAccessibility.cs Located in the shared .NET project
using System;
namespace Bitspace.Services
{
public class DeviceAccessibility
{
private static Lazy<IAccessibilityService> Implementation = new Lazy<IAccessibilityService>(() => CreateAccessibilityService(), System.Threading.LazyThreadSafetyMode.PublicationOnly);
public static IAccessibilityService Current
{
get
{
var curr = Implementation.Value;
if (curr == null)
{
throw new Exception();
}
return curr;
}
}
private static IAccessibilityService CreateAccessibilityService()
{
return new DeviceAccessibilityImplementation();
}
}
}
DeviceAccessibilityImplementation.cs Located in the Android project
using Android.Runtime;
namespace Bitspace.Services
{
[Preserve (AllMembers = true)]
public class DeviceAccessibilityImplementation : IAccessibilityService
{
public bool IsScreenReaderEnabled()
{
return true;
}
public void Announcement(string message)
{
}
public void NavigationAnnouncement(string message)
{
}
}
}
If I try to build the project, I get an error on the return new DeviceAccessibilityImplementation(); line in DeviceAccessibility.cs that says DeviceAccessibility.cs(25, 24): [CS0246] The type or namespace name 'DeviceAccessibilityImplementation' could not be found (are you missing a using directive or an assembly reference?)
However, CTRL Clicking on that line takes me to the DeviceAccessibilityImplementation.cs
I'm trying to write instrumentation test for my NetworkMonitorService as described in the official "testing your service" documentation.
Currently I'm stuck because I can't figure out how can I grab a reference to the started service in order to inject mocks into it and assert behavior.
My code:
#RunWith(AndroidJUnit4.class)
#SmallTest
public class NetworkMonitorServiceTest {
#Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule();
#Test
public void serviceStarted_someEventHappenedInOnStartCommand() {
try {
mServiceTestRule.startService(new Intent(
InstrumentationRegistry.getTargetContext(),
NetworkMonitorService.class));
} catch (TimeoutException e) {
throw new RuntimeException("timed out");
}
// I need a reference to the started service in order to assert that some event happened
// in onStartCommand()...
}
}
The service in question doesn't support binding. I think that if I'd implement support for binding and then use this in test in order to get a reference to the service it could work. However, I don't like writing production code just for sake of supporting test cases...
So, how can I test (instrumentation test) a Service that doesn't support binding?
Replace your application with special version "for tests". Do it by providing custom instrumentation test runner. Mock your dependencies it this "app for tests". See for details
Here is a simplified example how "app for test" can be used. Let's assume you want to mock network layer (eg. Api) during tests.
public class App extends Application {
public Api getApi() {
return realApi;
}
}
public class MySerice extends Service {
private Api api;
#Override public void onCreate() {
super.onCreate();
api = ((App) getApplication()).getApi();
}
}
public class TestApp extends App {
private Api mockApi;
#Override public Api getApi() {
return mockApi;
}
public void setMockApi(Api api) {
mockApi = api;
}
}
public class MyTest {
#Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule();
#Before public setUp() {
myMockApi = ... // init mock Api
((TestApp)InstrumentationRegistry.getTargetContext()).setMockApi(myMockApi);
}
#Test public test() {
//start service
//use mockApi for assertions
}
}
In the example dependency injection is done via application's method getApi. But you can use Dagger or any others approaches in the same way.
I found a very simple way for doing this. You can just perform a binding and you'll get the reference to the already running service, there are no conflicts with service creation because you already started it with onStartCommand, if you check you will see onCreate is called only once so you can be sure it is the same service. Just add the following after your sample:
Intent serviceIntent =
new Intent(InstrumentationRegistry.getTargetContext(),
NetworkMonitorService.class);
// Bind the service and grab a reference to the binder.
IBinder binder = mServiceRule.bindService(serviceIntent);
// Get the reference to the service
NetworkMonitorService service =
((NetworkMonitorService.LocalBinder) binder).getService();
// Verify that the service is working correctly however you need
assertThat(service, is(any(Object.class)));
I hope it helps.
this works at least for bound services:
#Test
public void testNetworkMonitorService() throws TimeoutException {
Intent intent = new Intent(InstrumentationRegistry.getTargetContext(), NetworkMonitorService.class);
mServiceRule.startService(intent);
IBinder binder = mServiceRule.bindService(intent);
NetworkMonitorService service = ((NetworkMonitorService.LocalBinder) binder).getService();
mServiceRule.unbindService();
}
to access fields, annotate with #VisibleForTesting(otherwise = VisibleForTesting.NONE)
I'm in the process of migrating my Android app to Retrofit 2.0. I had a custom ErrorHandler extending RetrofitError so I could react to different Http errors.
Now I understand I must create a custom CallAdapterFactory. I used the sample ErrorHandlingCallAdapter provided here.
My resulting CallAdapter is pretty much the same code, but if needed I could also post my code.
What's happening is that when I use this CallAdapterFactory, callbacks are not happening on the MainThread. I get android.view.ViewRootImpl$CalledFromWrongThreadException when trying to update the UI (which I always need to). I also don't want to always wrap my code with runOnUIThread in my callbacks.
I don't know if this helps, but when I log Thread.currentThread().getName() in my callbacks, it returns OkHttp.
I ended up passing an executor to my CallAdapter.Factory:
public static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
#Override
public void execute(#NonNull Runnable r) {
handler.post(r);
}
}
...
.addCallAdapterFactory(new ErrorHandlingCallAdapter.ErrorHandlingCallAdapterFactory(new MainThreadExecutor()))
and wrapping the callback in:
callbackExecutor.execute(new Runnable() {
#Override
public void run() {
}
});
I inspired myself from this.
You don't need to create a new executor, you can use retrofit's :
public AuthCall adapt(Call call) {
return new CustomCall(call, statuses, retrofit.callbackExecutor());
}
keep a reference of it in your adapted calls, and then use it within your callback:
customCall.enqueue(new Callback() {
executor.execute(...
The following message Handler works fine receiving messages from my service...
private Handler handler = new Handler()
{
public void handleMessage(Message message)
{
Object path = message.obj;
if (message.arg1 == 5 && path != null) //5 means its a single mapleg to plot on the map
{
String myString = (String) message.obj;
Gson gson = new Gson();
MapPlot mapleg = gson.fromJson(myString, MapPlot.class);
myMapView.getOverlays().add(new DirectionPathOverlay(mapleg.fromPoint, mapleg.toPoint));
mc.animateTo(mapleg.toPoint);
}
else
{
if (message.arg1 == RESULT_OK && path != null)
{
Toast.makeText(PSActivity.this, "Service Started" + path.toString(), Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(PSActivity.this,"Service error" + String.valueOf(message.arg1), Toast.LENGTH_LONG).show();
}
}
};
};
However, even though it tests out alright in the AVD (I'm feeding it a large KML file via DDMS) the "object path = message.obj;" line has a WARNING saying "this Handler class should be static else leaks might occur".
But if I say "static Handler handler = new Handler()" it won't compile complaining that I "cannot make a static reference to a non-static field myMapView. If I can't make such references, I can't do anything useful.
This led me into several hours of googling around on this issue and learning more about weakReferences than I ever wanted to know. The often found reccomendation I find is that I should replace...
private Handler handler = new Handler()
with
static class handler extends Handler
{
private final WeakReference<PSActivity> mTarget;
handler(PSActivity target)
{
mTarget = new WeakReference<PSActivity>(target);
}
But this won't compile still complaining that I can't make a static reference to a non-dtatic field. So, my question a week or to ago was "how can I write a message handler for android so my service can send data to my activity. Even though I have working code, the question still stands with the suffix "without leaking memory".
Thanks, Gary
I got the same warning message when I tried to use handler in a Service, and finally resolved it by taking the advice from this thread, see the code snippet from my project.
public class MyService extends Service {
...
private MyHandler mHandler;
public static class MyHandler extends Handler {
private final WeakReference<MyService> mService;
MyHandler(MyService service) {
mService = new WeakReference<MyService>(service);
}
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MyService service = mService.get();
if (service!=null) {
if (msg.what==MSG_RESUME_CHECKING) {
service.pause();
} else if (msg.what==MSG_PAUSE_CHECKING) {
service.resume();
}
}
}
}
...
#Override
public void onCreate() {
super.onCreate();
...
mHandler = new MyHandler(this);
...
}
}
I know I'm a little late to the party, but hopefully this helps further answer the question for future inquirers.
As you discovered through your Googling (something I've done quite a bit of myself to solve a similar issue) you need to turn your Handler instance into a static inner class (nested class) which takes the target Activity in its constructor. It then converts this Activity reference into a WeakReference and that is what can be used to interact with things in your target Activity. In your case:
Toast.makeText(mTarget.get().this, "Service Started" + path.toString(), Toast.LENGTH_LONG).show();
Since you're changing to a nested class you'll also need to create an instance of that class for your Thread to access in its run() method. For more help on this (as well as on how to make sure your app works even after configuration changes) see this question.
Hope this helps!
I am working on a project hosted on AppEngine, and for the browser client I am using the GWTP platform which implies using GIN (on the client) and GUICE on the server. Also, it uses Models, presenters, actions and events.
I am thinking of also writing an android client for the service but I don't know how to start because I don't know how to connect and exchange data with the webservice. I would have to use Actions and Action Handlers ( http://code.google.com/p/gwt-platform/wiki/GettingStartedDispatch ) which I use for the browser client. From Android I only know how to do it with RPC, and I can't make the connection, I don't know how to map classes from the device to the server.
For example, by using GWTP, if on the browser client I want to do something on the server, I implement an Action class, an ActionResult class ( both on the client ) and an ActionHandler class (on the server). To dispatch an action, I use the DispatchAsync interface and to get the result I use AsyncCallback.
Action (on the client ) - SendRoadNotification.java :
public class SendRoadNotification extends
ActionImpl<SendRoadNotificationResult> {
private RoadNotification roadNot;
#SuppressWarnings("unused")
private SendRoadNotification() {
// For serialization only
}
public SendRoadNotification(RoadNotification roadNot) {
this.roadNot = roadNot;
}
public RoadNotification getRoadNot() {
return roadNot;
}
}
ActionResult (on the client ) -- SendRoadNotfifcationResult.java :
public class SendRoadNotificationResult implements Result {
private RoadNotification roadNot;
#SuppressWarnings("unused")
private SendRoadNotificationResult() {
// For serialization only
}
public SendRoadNotificationResult(RoadNotification roadNot) {
this.roadNot = roadNot;
}
public RoadNotification getRoadNot() {
return roadNot;
}
}
ActionHandler ( on the server ) -- SendRoadNotificationActionHandler.java :
public class SendRoadNotificationActionHandler implements
ActionHandler<SendRoadNotification, SendRoadNotificationResult> {
static DataStore ds = DataStore.getDatastoreService();
#Inject
public SendRoadNotificationActionHandler() {
}
#Override
public SendRoadNotificationResult execute(SendRoadNotification action,
ExecutionContext context) throws ActionException {
//Here I am doing something with that action
}
#Override
public void undo(SendRoadNotification action,
SendRoadNotificationResult result, ExecutionContext context)
throws ActionException {
}
#Override
public Class<SendRoadNotification> getActionType() {
return SendRoadNotification.class;
}
}
The way I use those, is:
SendRoadNotification action = new SendRoadNotification(rn);
dispatchAsync.execute(action, sendRoadNotifCallback);
And the callback:
AsyncCallback<SendRoadNotificationResult> sendRoadNotifCallback = new AsyncCallback<SendRoadNotificationResult>() {
#Override
public void onSuccess(SendRoadNotificationResult result) {
}
#Override
public void onFailure(Throwable caught) {
Window.alert("Something went wrong");
}
};
How can I implement this in android ? Can somebody give me an example or had this problem before ?
I am using AppEngine sdk 1.6.4, GWT sdk 2.4.0, GWTP plugin for Eclipse and GPE plugin for Eclipse.
You might want to look at the source the GAE plugin for ADT generates for 'App Engine Connected Android apps' for inspiration. They are doing something similar by calling GWT endpoints using Android's HttpClient.
https://developers.google.com/eclipse/docs/appengine_connected_android