Always move to specific uiviewcontroller - uiviewcontroller

I have a IOS app, that uses a network connection, and at times, it looses this network connection, whenever it does, I want the app to move back to a specific UIViewController.. What is the best way to achieve this?
Can I do this from the appDelegate?

Are you using the Reachability class described in the Apple documentation? If not, you should take a look at it. It will give you network status, including whether you are connected to the internet. It has a notification of network status change so you can put an observer in you app delegate or anywhere else you need it to accomplish your objective.
There is a lot of help already available on the web with examples on how to use Reachability, and this one may be something you can start with.
Update
Raachability change notifications can be used to inform your app when the connection is lost or restored. See the notification statement in the code below for the Reachability class;
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target, flags)
NSCAssert(info != NULL, #"info was NULL in ReachabilityCallback");
NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], #"info was wrong class in ReachabilityCallback");
//We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
// in case someon uses the Reachablity object in a different thread.
NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
Reachability* noteObject = (Reachability*) info;
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
[myPool release];
}
For this to work you have to call startNotifier:
- (BOOL) startNotifier
{
BOOL retVal = NO;
SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
{
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
{
retVal = YES;
}
}
return retVal;
}

Related

Trying to get C++/WinRT non UWP program to recognize bluetooth LE devices: specific failure at get_weak() (error:not defined)

I'm taking a shot at using C++/WinRT to find and communicate with Bluetooth LE devices in a non-UWP app.
(I'm trying to avoid UWP, as there appear to be some constraints on what you can do with it, and it looks kind of bloated to me.)
My background is a lot of programming and releasing for small-group distribution old-fashioned C++ WinMain-based programming, as in Petzold's "Programming Windows 95". My experience has been using the Win32 API only.
Unfortunately for me, MS documentation indicates that Bluetooth LE is not supported in Win32, and only in WinRT. Thus, this forces me to use something like C++/WinRT to access the API.
So, I took a shot at it by downloading the only available example of bluetooth LE access in C++ which I know of at all, which is Microsoft's C++WinRT UWP example.
I got that running as one Visual Studio 2022 project, and, since I am looking for a non-UWP program, I tried putting the relevant stuff into another project, for which I used Microsoft VS2022's built-in template for a C++/WinRT Console. When I try to stick into that what appearVS says to be the key elements of the C++/WinRT UWP example, and make modifications to fix obvious problems, I have an error in the code which I have no idea how to fix: it is on the several get_weak() calls, which VS intellisense says are "undefined". (The compile also fails with unable to find main.g.h and main.g.cpp .
Here is the code:
File main.h:
#pragma once
#include "main.g.h"
class find_devs
{
find_devs() {};
private:
std::vector<Windows::Devices::Enumeration::DeviceInformation> UnknownDevices;
Windows::Devices::Enumeration::DeviceWatcher deviceWatcher{ nullptr };
event_token deviceWatcherAddedToken;
event_token deviceWatcherUpdatedToken;
event_token deviceWatcherRemovedToken;
event_token deviceWatcherEnumerationCompletedToken;
event_token deviceWatcherStoppedToken;
void StartBleDeviceWatcher();
void StopBleDeviceWatcher();
std::vector<Windows::Devices::Enumeration::DeviceInformation>::iterator FindUnknownDevices(hstring const& id);
fire_and_forget DeviceWatcher_Added(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformation deviceInfo);
fire_and_forget DeviceWatcher_Updated(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformationUpdate deviceInfoUpdate);
fire_and_forget DeviceWatcher_Removed(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformationUpdate deviceInfoUpdate);
fire_and_forget DeviceWatcher_EnumerationCompleted(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Foundation::IInspectable const&);
fire_and_forget DeviceWatcher_Stopped(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Foundation::IInspectable const&);
};
and main.cpp:
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Devices::Enumeration;
#include "pch.h"
#include "main.h"
#include "main.g.cpp"
using namespace winrt;
using namespace Windows::Devices::Enumeration;
using namespace Windows::Foundation;
namespace winrt
{
hstring to_hstring(DevicePairingResultStatus status)
{
switch (status)
{
case DevicePairingResultStatus::Paired: return L"Paired";
case DevicePairingResultStatus::NotReadyToPair: return L"NotReadyToPair";
case DevicePairingResultStatus::NotPaired: return L"NotPaired";
case DevicePairingResultStatus::AlreadyPaired: return L"AlreadyPaired";
case DevicePairingResultStatus::ConnectionRejected: return L"ConnectionRejected";
case DevicePairingResultStatus::TooManyConnections: return L"TooManyConnections";
case DevicePairingResultStatus::HardwareFailure: return L"HardwareFailure";
case DevicePairingResultStatus::AuthenticationTimeout: return L"AuthenticationTimeout";
case DevicePairingResultStatus::AuthenticationNotAllowed: return L"AuthenticationNotAllowed";
case DevicePairingResultStatus::AuthenticationFailure: return L"AuthenticationFailure";
case DevicePairingResultStatus::NoSupportedProfiles: return L"NoSupportedProfiles";
case DevicePairingResultStatus::ProtectionLevelCouldNotBeMet: return L"ProtectionLevelCouldNotBeMet";
case DevicePairingResultStatus::AccessDenied: return L"AccessDenied";
case DevicePairingResultStatus::InvalidCeremonyData: return L"InvalidCeremonyData";
case DevicePairingResultStatus::PairingCanceled: return L"PairingCanceled";
case DevicePairingResultStatus::OperationAlreadyInProgress: return L"OperationAlreadyInProgress";
case DevicePairingResultStatus::RequiredHandlerNotRegistered: return L"RequiredHandlerNotRegistered";
case DevicePairingResultStatus::RejectedByHandler: return L"RejectedByHandler";
case DevicePairingResultStatus::RemoteDeviceHasAssociation: return L"RemoteDeviceHasAssociation";
case DevicePairingResultStatus::Failed: return L"Failed";
}
return L"Code " + to_hstring(static_cast<int>(status));
}
}
// This scenario uses a DeviceWatcher to enumerate nearby Bluetooth Low Energy devices,
// displays them in a ListView, and lets the user select a device and pair it.
// This device will be used by future scenarios.
// For more information about device discovery and pairing, including examples of
// customizing the pairing process, see the DeviceEnumerationAndPairing sample.
#pragma region UI Code
#pragma endregion
#pragma region Device discovery
/// <summary>
/// Starts a device watcher that looks for all nearby Bluetooth devices (paired or unpaired).
/// Attaches event handlers to populate the device collection.
/// </summary>
void find_devs::StartBleDeviceWatcher()
{
// Additional properties we would like about the device.
// Property strings are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/ff521659(v=vs.85).aspx
auto requestedProperties = single_threaded_vector<hstring>({ L"System.Devices.Aep.DeviceAddress", L"System.Devices.Aep.IsConnected", L"System.Devices.Aep.Bluetooth.Le.IsConnectable" });
// BT_Code: Example showing paired and non-paired in a single query.
hstring aqsAllBluetoothLEDevices = L"(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";
deviceWatcher =
Windows::Devices::Enumeration::DeviceInformation::CreateWatcher(
aqsAllBluetoothLEDevices,
requestedProperties,
DeviceInformationKind::AssociationEndpoint);
// Register event handlers before starting the watcher.
deviceWatcherAddedToken = deviceWatcher.Added({ get_weak(), &DeviceWatcher_Added });
deviceWatcherUpdatedToken = deviceWatcher.Updated({ get_weak(), &DeviceWatcher_Updated });
deviceWatcherRemovedToken = deviceWatcher.Removed({ get_weak(), &DeviceWatcher_Removed });
deviceWatcherEnumerationCompletedToken = deviceWatcher.EnumerationCompleted({ get_weak(), &DeviceWatcher_EnumerationCompleted });
deviceWatcherStoppedToken = deviceWatcher.Stopped({ get_weak(), &DeviceWatcher_Stopped });
// Start the watcher. Active enumeration is limited to approximately 30 seconds.
// This limits power usage and reduces interference with other Bluetooth activities.
// To monitor for the presence of Bluetooth LE devices for an extended period,
// use the BluetoothLEAdvertisementWatcher runtime class. See the BluetoothAdvertisement
// sample for an example.
deviceWatcher.Start();
}
/// <summary>
/// Stops watching for all nearby Bluetooth devices.
/// </summary>
void find_devs::StopBleDeviceWatcher()
{
if (deviceWatcher != nullptr)
{
// Unregister the event handlers.
deviceWatcher.Added(deviceWatcherAddedToken);
deviceWatcher.Updated(deviceWatcherUpdatedToken);
deviceWatcher.Removed(deviceWatcherRemovedToken);
deviceWatcher.EnumerationCompleted(deviceWatcherEnumerationCompletedToken);
deviceWatcher.Stopped(deviceWatcherStoppedToken);
// Stop the watcher.
deviceWatcher.Stop();
deviceWatcher = nullptr;
}
}
std::vector<Windows::Devices::Enumeration::DeviceInformation>::iterator FindUnknownDevices(hstring const& id)
{
}
fire_and_forget find_devs::DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
{
}
fire_and_forget find_devs::DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
auto deviceInfo = FindUnknownDevices(deviceInfoUpdate.Id());
if (deviceInfo != UnknownDevices.end())
{
deviceInfo->Update(deviceInfoUpdate);
// If device has been updated with a friendly name it's no longer unknown.
}
}
}
fire_and_forget find_devs::DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
auto deviceInfo = FindUnknownDevices(deviceInfoUpdate.Id());
if (deviceInfo != UnknownDevices.end())
{
UnknownDevices.erase(deviceInfo);
}
}
}
fire_and_forget find_devs::DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, IInspectable const&)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
}
}
fire_and_forget DeviceWatcher_Stopped(DeviceWatcher sender, IInspectable const&)
{
// Access this->deviceWatcher on the UI thread to avoid race conditions.
auto lifetime = get_strong();
co_await resume_foreground(Dispatcher());
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
}
}
#pragma endregion
int main()
{
init_apartment();
Uri uri(L"http://aka.ms/cppwinrt");
printf("Hello, %ls!\n", uri.AbsoluteUri().c_str());
}
and, for completeness, this is pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Devices.Enumeration.h>
The code is, I know, not complete. I haven't created a DeviceWatcher, etc., but I am apparently blocked in that I can't get the get_weaks() to pass intellisense screening or to compile.
Any guidance from people who know about this stuff would be great.
Bear in mind: I, myself, pretty much don't know what's going on. Due to the complexity, from my Win32 Petzold-style background, of the example MS C++/WinRT UWP example. It has all kinds of stuff in the Solution Explorer. There are .idl files, a packages.config, a bunch of different Xaml files, some generated c++ files. All this stuff is beyond my understanding, and I have not been able to pick it up with any speed from the MS documentation I can find.
(All I have figured out is that C++/WinRT is some sort of a thing where there are generated header and perhaps other files that are supposed to make your C++ code look like it's directly accessing WinRT classes. And, I have seen MS write that you can use winRT in non-UWP applications. Otherwise, I am lost.)

MVC5 AntiForgeryToken - how to handle "The provided anti-forgery token was meant for user "", but the current user is "xxx"." exception?

I want to protect our login actions by AntiforgeryToken attribute - I know why the exception from the topic occurs, however I can't seem to find any good solution for it.
Let say we have the following situations:
It's 8:00 AM, application users are coming to work, they sit down and starting the login process - right now it is very possible that some of the users will get the same ValidationToken. After the first one logs in - all other will see the above exception (or some other custom exception screen) when they attempt to login.
Some user logged in, then accidentally pressed the "back" button and attempted to log in again - while this is more unlikely, it can happen, and I don't want users to see exceptions when it does.
So the question is simple - how to prevent the above situations, or how to handle them so that users won't notice anything. I have tried the following:
Setting the AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start in Global.asax - it didn't fix the problem, I still get the same exception
Setting the [OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")] on the method with [ValidateAntiForgeryToken] attribute - again, no luck there
Right now I was thinking to manually validate the token in action body, catch the error, and check if attempt was made by anonymous user:
public ActionResult SomeAction()
{
try
{
AntiForgery.Validate();
}
catch(HttpAntiForgeryException ex)
{
if(String.IsNullOrEmpty(HttpContext.User.Identity.Name))
{
throw;
}
}
//Rest of action body here
//..
//..
}
The above seems to prevent the errors - but is it safe? What alternatives are there?
Thanks in advance.
Best regards.
EDIT:
The final "solution" was to disable token validation on login form - there may be a better way to handle it, but it seems that all solutions I found, were ugly workarounds similar to mine proposed above.
Since there is no way to know how "safe" those alternatives are (if they are safe at all), we decided to do disable token validation on login.
Try setting (in global.cs):
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
This will add the name identifier to your token,
As for the double login issue try to use a script to document the date and time of the original submit to stop a second submit with the same token.
// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
$(this).on('submit',function(e){
var $form = $(this);
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
$form.data('submitted', true);
}
});
// Keep chainability
return this;
};
So we know one thing; users like the back button and have a habit of the double click, this is a big issue with AntiforgeryToken.
But depending on what your application does there are ways to limit their compulsion to do so. The simplest of which is to do your best to try and make the visitor not feel like they need to “rewind” their request to alter it.
Ensure that form error messaging is clear and concise to ensure the
user knows what is wrong. Contexual errors give bonus points.
Always maintain form state between form submissions. Apart from
passwords or credit card numbers, there’s no excuse thanks the to MVC
form helpers. #Html.LabelFor(x => x.FirstName)
If forms are spread across tabs or hidden divs such as those used in
SPA frameworks like Angular or ember.js, be smart and show the
controller layouts or form that the errors actually originated from in
the form submission when displaying the error. Don’t just direct them
to the home controller or first tab.
“What’s going on?” - Keeping the user informed
When a AntiForgeryToken doesn’t validate your website will throw an Exception of type System.Web.Mvc.HttpAntiForgeryException.
If you’ve set up correctly you’ve got friendly errors turned on and this will mean your error page will not show an Exception and show a nice error page that tells them what is up.
You can make this a little easier by at least giving the user a more informative page targeted at these exceptions by catching the HttpAntiForgeryException.
private void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex is HttpAntiForgeryException)
{
Response.Clear();
Server.ClearError(); //make sure you log the exception first
Response.Redirect("/error/antiforgery", true);
}
}
and your /error/antiforgery view can tell them Sorry you have tried to submit the same information twice
Another Idea is to log the error and return the user to the login screen:
Create a HandleAntiforgeryTokenErrorAttribute class that Overrides the OnException method.
HandleAntiforgeryTokenErrorAttribute.cs:
public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { action = "Login", controller = "Account" }));
}
}
Global Filter:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new HandleAntiforgeryTokenErrorAttribute()
{ ExceptionType = typeof(HttpAntiForgeryException) }
);
}
}
I would also use a few tools to record all your information as login is critical part of your application
NLog for general logging and emails on critical application exceptions (including web exceptions).
Elmah for filtering and email of web exceptions.
EDIT:
Also you may want to look at a jQuery plugin called SafeForm. Link
EDIT:
I have seen allot of debate on this and everyone's views on the subject have valid points, How i look at it is (Taken from owasp.org)
Cross-Site Request Forgery (CSRF) is an attack that forces an end user
to execute unwanted actions on a web application in which they're
currently authenticated, CSRF attacks specifically target state-changing requests, not theft of data. The anti-forgery token is
specific to 'who is logged on'. So once you login, then go back, the
old token is no longer valid
Now i also use authorized IP addresses for login to allot of my applications with 2 factor authorization if the users IP address changes, so if Cross-Site Request Forgery was in play the user wouldn't match the IP address and request 2 factor authorization. almost like the way a security router would work. but if you want to keep it on your login page i don't see a problem as long as you have your friendly error pages set up people will not get upset as they will see they did something wrong.
I just wanted to add to the pool pro's answer - regarding the Filter part - that one must be careful since that will override all the exceptions about AntiforgeryToken, and if you (like myself) have this token validation on other parts of your application you might consider adding some validation to the filter:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new HandleAntiforgeryTokenErrorAttribute() { ExceptionType = typeof(HttpAntiForgeryException) });
}
}
public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
string actionName = filterContext.Controller.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = filterContext.Controller.ControllerContext.RouteData.Values["controller"].ToString();
if (actionName.ToLower() == "login" && controllerName.ToLower() == "account")
{
//Handle Error
//In here you handle the error, either by logging, adding notifications, etc...
//Handle Exception
filterContext.ExceptionHandled = true;
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { action = "Login", controller = "Account" }));
}
else
{
base.OnException(filterContext);
}
}
}
Note that I separate the cases where this exception is thrown on the Account/Login method, from all the other mehtods where a [ValidateAntiForgeryToken] might be used.

windows 8 app FileOpenPicker np file info

I'm trying to get some file information about a file the user select with the FileOpenPicker, but all the information like the path and name are empty. When I try to view the object in a breakpoint I got the following message:
file = 0x03489cd4 <Information not available, no symbols loaded for shell32.dll>
I use the following code for calling the FileOpenPicker and handeling the file
#include "pch.h"
#include "LocalFilePicker.h"
using namespace concurrency;
using namespace Platform;
using namespace Windows::Storage;
using namespace Windows::Storage::Pickers;
const int LocalFilePicker::AUDIO = 0;
const int LocalFilePicker::VIDEO = 1;
const int LocalFilePicker::IMAGES = 2;
LocalFilePicker::LocalFilePicker()
{
_init();
}
void LocalFilePicker::_init()
{
_openPicker = ref new FileOpenPicker();
_openPicker->ViewMode = PickerViewMode::Thumbnail;
}
void LocalFilePicker::askFile(int categorie)
{
switch (categorie)
{
case 0:
break;
case 1:
_openPicker->SuggestedStartLocation = PickerLocationId::VideosLibrary;
_openPicker->FileTypeFilter->Append(".mp4");
break;
case 2:
break;
default:
break;
}
create_task(_openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
{
if (file)
{
int n = 0;
wchar_t buf[1024];
_snwprintf_s(buf, 1024, _TRUNCATE, L"Test: '%s'\n", file->Path);
OutputDebugString(buf);
}
else
{
OutputDebugString(L"canceled");
}
});
}
Can anybody see whats wrong with the code or some problems with settings for the app why it isn't work as expected.
First an explanation why you are having trouble debugging, this is going to happen a lot more when you write WinRT programs. First, do make sure that you have the correct debugging engine enabled. Tools + Options, Debugging, General. Ensure that the "Use Managed Compatibility Mode" is turned off.
You can now inspect the "file" option, it should resemble this:
Hard to interpret of course. What you are looking at is a proxy. It is a COM term, a wrapper for COM objects that are not thread-safe or live in another process or machine. The proxy implementation lives in shell32.dll, thus the confuzzling diagnostic message. You can't see the actual object at all, accessing its properties requires calling proxy methods. Something that the debugger is not capable of doing, a proxy marshals the call from one thread to another, that other thread is frozen while the debugger break is active.
That makes you pretty blind, in tough cases you may want to write a littler helper code to store the property in a local variable. Like:
auto path = file->Path;
No trouble inspecting or watching that one. You should now have confidence that there's nothing wrong with file and you get a perfectly good path. Note how writing const wchar_t* path = file->Path; gets you a loud complaint from the compiler.
Which helps you find the bug, you can't pass a Platform::String to a printf() style function. Just like you can't with, say, std::wstring. You need to use an accessor function to convert it. Fix:
_snwprintf_s(buf, 1024, _TRUNCATE,
L"Test: '%s'\n",
file->Path->Data());

Windows phone 8 notification hub unregister

Can someone show me or tell some example how to unregister from notification hub in windows phone 8. I tried on this way but it doesn't work.
public void registerForNotifications(string[] tags)
{
var channel = HttpNotificationChannel.Find("xxx");
if (channel == null)
{
channel = new HttpNotificationChannel("xxx");
channel.Open();
channel.BindToShellToast();
}
string[] tagsToSubscribeTo = tags;
channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(async (o, args) =>
{
var hub = new NotificationHub("xxx", "xxx");
await hub.RegisterNativeAsync(args.ChannelUri.ToString(), tagsToSubscribeTo);
});
}
public async void unregisterFromNotifications()
{
var channel = HttpNotificationChannel.Find("xxx");
var hub = new NotificationHub("xxx", "xxx");
await hub.UnregisterAllAsync(channel.ChannelUri.ToString());
}
You didn't say what "it didn't work" means. Did you get an error message? Did it report success but actually fail? In your questions, it really helps more if you share those things. But I'll take a stab at this anyway.
I suspect that you might be using the DefaultListenSharedAccessSignature endpoint from your Windows Phone 8 app.
According to http://msdn.microsoft.com/en-us/library/dn495373.aspx, the Listen access level grants permission to:
Create/Update registration.
Read registration.
Read all registrations for a handle.
Delete registration.
Reading that last one, I wonder if the UnregisterAllAsync method might require a higher access level to delete all registrations, rather than just one.
But rather than use the DefaultFullSharedAccessSignature endpoint, I would rather just try the UnregisterAsync method instead of UnregisterAllAsync.
Disclaimer: I have not tried this out. It may not help at all.

Can I turn on WiFi-Direct from code? on Android API-14 (ICS)

I'm using the new Wi-Fi Direct API from google on Android 4.0
and in Sample code they send the User to Settings, to activate WiFi -Direct Mode.
Is there a way to Start it by code???
all they offer is to listen to WIFI_P2P_STATE_CHANGED_ACTION intent, and then use this code
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
// UI update to indicate wifi p2p status.
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wifi Direct mode is enabled
} else {
// Wifi Direct mode is disabled
}
Yes there is a way using reflection. Works on my GSII (and fails gracefully on non Wifi Direct HTC Sensation) but as this is reflection it may not work on all phones.
p2pManager = (WifiP2pManager) getSystemService(WIFI_P2P_SERVICE);
channel = p2pManager.initialize(getApplicationContext(),
getMainLooper(), null);
try {
Class<?> wifiManager = Class
.forName("android.net.wifi.p2p.WifiP2pManager");
Method method = wifiManager
.getMethod(
"enableP2p",
new Class[] { android.net.wifi.p2p.WifiP2pManager.Channel.class });
method.invoke(p2pManager, channel);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Please note:
On Jelly Bean and above, when you try to use the WifiP2pManager API, WiFi-Direct is automatically enabled (as long as WiFi is on), so there is no need to use this hack.
No, all you could do is notify the user to turn on WiFi.
On some devices, even though Wi-Fi direct is supported, it's not enabled due to some system bugs. Here's a more reliable way to check whether it's enabled (unfortunately it requires root) using Kotlin.
val matcher = "^mNetworkInfo .* (isA|a)vailable: (true|false)"
.toPattern(Pattern.MULTILINE)
.matcher(su("dumpsys ${Context.WIFI_P2P_SERVICE}"))
if (!matcher.find()) return "Root unavailable"
if (matcher.group(2) != "true") return "Wi-Fi Direct unavailable"
return "Wi-Fi Direct available"
This should work for Android 4.3 - 8.1. Check source code below:
https://android.googlesource.com/platform/frameworks/base/+/f0afe4144d09aa9b980cffd444911ab118fa9cbe%5E%21/wifi/java/android/net/wifi/p2p/WifiP2pService.java
https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/a8d5e40/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java#639
https://android.googlesource.com/platform/frameworks/base.git/+/f0afe4144d09aa9b980cffd444911ab118fa9cbe/core/java/android/net/NetworkInfo.java#433
https://android.googlesource.com/platform/frameworks/base.git/+/220871a/core/java/android/net/NetworkInfo.java#415