"There’s a new key for the Info.plist file: NSBluetoothAlwaysUsageDescription, which you can use to explain how and why your app uses Bluetooth. In contrast to the existing NSBluetoothPeripheralUsageDescription, the new description will be shown as part of the new pop-up, and also in the Settings app on the Bluetooth Privacy screens."
After updating to iOS 13, our app experienced crashes, as I'm sure many did. Our problem was due to not including the newly required bluetooth key in the Xamarin.iOS projects Info.plist file.
However after adding this upon loading the first "action" that occurs is presenting the user with the new Bluetooth access prompt.
We aren't clearly seeing how to capture the response to this prompt. In-fact after this prompt is interacted with the app has no "return" point as it were. Can't quite find a break-point for the prompt interaction / result handling and our app never returns from the prompt. It's running but the next "action" to occur never happens.
So- how to capture/handle user's interaction with the new Bluetooth prompt in iOS 13?
NOTE*: To be absolutely transparent - our application doesn't initialize any instance of CBCentralManager rather it takes advantage of a native framework that itself utilizes Bluetooth LE internally (out of our control).
Our case might be quite unique but for those experiencing this implement CBCentralManager and utilize its UpdatedState method to capture user interaction with the newly presented Bluetooth dialogue.
Initialization called in page creation of our Apps MainPage
BleManager = new BluetoothManager();
Class
using System;
using CoreBluetooth;
namespace MyApp.iOS.Classes
{
public class BluetoothManager
{
public CBCentralManager CentralBleManager
{
get { return this.bleCntrlMgr; }
}
protected CBCentralManager bleCntrlMgr;
protected CBCentralManagerDelegate bleMgrDel;
public BluetoothManager()
{
this.bleCntrlMgr = new CoreBluetooth.CBCentralManager();
this.bleCntrlMgr.UpdatedState += BleMgr_UpdatedState;
}
private void BleMgr_UpdatedState(object sender, EventArgs e)
{
Console.WriteLine("UpdatedState: {0}", bleCntrlMgr.State);
if (bleCntrlMgr.State == CBCentralManagerState.PoweredOn
|| bleCntrlMgr.State == CBCentralManagerState.PoweredOff
|| bleCntrlMgr.State == CBCentralManagerState.Resetting
|| bleCntrlMgr.State == CBCentralManagerState.Unauthorized
|| bleCntrlMgr.State == CBCentralManagerState.Unsupported)
{
/* return point */
// i.e.: CallMethod();
}
else if (bleCntrlMgr.State == CBCentralManagerState.Unknown)
{
/* <-- request access --> */
}
}
}
}
Related
I´m getting this error when procedure NotificationsRegistrationHandler is executed at application startup.
java.lang.IllegalStateException: Object NotificationsRegistrationHandler only supports OFFLINE but is being called via RemoteApplicationServer
As documentation says:
If you have a completely offline application and you need this Registration Handler procedure to be generated offline exclusively, set Main property = False and Connectivity Support property = Offline
I have set my main SD object Registration Handler property to use this procedure.
I have also set the following properties on procedure NotificationsRegistrationHandler:
What it´s wrong with my code or configuration?
Thanks,
Rogelio Arosemena
Rogelio,
I think that this may be an issue with offline mode. We can check it out.
In the meantime, you could set to Connectivity Support = Online and this should fix your issue.
I found an alternative solution by creating an external object on Android to return One Signal Id. The code was:
OneSignal.idsAvailable(new OneSignal.IdsAvailableHandler() {
#Override
public void idsAvailable(String userId, String registrationId) {
try{
return userId;
}catch(Exception e){
e.printStackTrace();
return "";
}
}
});
Device registration on One Signal was ok on SD application. The problem was that procedure NotificationRegistrationHandler was never executed (offline or online), so we can't store DeviceToken on our table.
We will have to do the same for IOS with this code:
OSPermissionSubscriptionState status = OneSignal.getPermissionSubscriptionState();
status.getSubscriptionStatus().getUserId();
how are you ? I have a detail with the push after updating the tab that contains my grid, I am using vaadin 8.0.4
,google chrome updated, and my example is based here https://github.com/vaadin/archetype-application-example
My application consists of data stored in mongodb, when I make a direct change in the db it is reflected in the grid every so often, 30 seconds, with push, it always works on a single tab, the problem appears when I update the tab or create a new one, the push seems to be disconnected and my grid is not updated anymore, the strange thing is that I added the #PreserveOnRefresh and in the first tab that accesses the application in that if the push works even after updating very strange.
This instance check changes in my db
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
and
I use the grid update, with
grid.getDataProvider().refreshAll()
I even try to broadcast the tabs, by means of the pattern described in the book 12.16.4. Broadcasting to Other Users
because if the active notifications continue in all the tabs, but the grid does not, only in the original tab.
Update:
In this example application the problem is actually the login, when I remove it if everything works perfectly as it should be with push. But only when I remove the login
#Override
public void receiveBroadcast() {
access(() -> {
//Notification.show(message);
//grid.getDataProvider().refreshAll();
getNavigator().removeView(MonitorCrudView.VIEW_NAME);
getNavigator().addView(MonitorCrudView.VIEW_NAME,new MonitorCrudView(this));
getNavigator().navigateTo(MonitorCrudView.VIEW_NAME);
Notification.show("Grid updated", Notification.Type.TRAY_NOTIFICATION);
});
}
The detail is that when I have the AccessContro enabled, and I enter as admin by what you see, when executing the above method I get an exception of type "No request linked to the current thread"; Coming from the "CurrentUser" Class
https://github.com/vaadin/archetype-application-example/blob/master/mockapp-ui/src/main/java/org/vaadin/mockapp/samples/authentication/CurrentUser.java
But here in vaadin 8.0.4 changes a little
public final class CurrentUser {
/**
* The attribute key used to store the username in the session.
*/
public static final String CURRENT_USER_SESSION_ATTRIBUTE_KEY = CurrentUser.class
.getCanonicalName();
private CurrentUser() {
}
/**
* Returns the name of the current user stored in the current session, or an
* empty string if no user name is stored.
*
* #throws IllegalStateException
* if the current session cannot be accessed.
*/
public static String get() {
String currentUser = (String) getCurrentRequest().getWrappedSession()
.getAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY);
if (currentUser == null) {
return "";
} else {
return currentUser;
}
}
/**
* Sets the name of the current user and stores it in the current session.
* Using a {#code null} username will remove the username from the session.
*
* #throws IllegalStateException
* if the current session cannot be accessed.
*/
public static void set(String currentUser) {
if (currentUser == null) {
getCurrentRequest().getWrappedSession().removeAttribute(
CURRENT_USER_SESSION_ATTRIBUTE_KEY);
} else {
getCurrentRequest().getWrappedSession().setAttribute(
CURRENT_USER_SESSION_ATTRIBUTE_KEY, currentUser);
}
}
private static VaadinRequest getCurrentRequest() {
VaadinRequest request = VaadinService.getCurrentRequest();
if (request == null) {
throw new IllegalStateException(
"No request bound to current thread");
}
return request;
}
}
UPDATE:
Https://github.com/rucko24/testView/blob/master/MyApp-ui/src/main/java/example/samples/crud/SampleCrudView.java
In this class I added the button that broadcast to all UI.
Log in as admin
Click on Update grid
Should give a type exception
java.util.concurrent.ExecutionException:
java.lang.IllegalStateException: No request bound to current thread
Does not continue to throw exeption after refreshing the UI
But when opening in an incognito tab it always throws the exception once before updating.
With the base project and mongo db plus the
private static ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool (5);
I always get the same exception from above, and never change the view with push
Disclaimer: This is better suited as a comment but it does not fit the allocated space.
The VaadinService.getCurrentRequest() API doc states that:
The current response can not be used in e.g. background threads because of the way server implementations reuse response instances.
At the same time, the UI.access() javadoc is somewhat ambiguous stating that:
Please note that the runnable might be invoked on a different thread or later on the current thread, which means that custom thread locals might not have the expected values when the command is executed
The above statements kind of explain why VaadinService.getCurrentRequest() is null in your getCurrentRequest() method.
Nonetheless, it seems that UI.getCurrent() returns an instance when running in that background thread, also suggested by this vaadin forum post and vaadin book:
Your code is not thread safe as it does not lock the VaadinSession before accessing the UI. The preferred pattern is using the UI.access and VaadinSession.access methods as described in Book of Vaadin section 11.16.3. Inside an access block Vaadin automatically sets the relevant threadlocals in addition to properly handling session locking.
In conclusion, i'd suggest to replace all the calls to getCurrentRequest().getWrappedSession() with UI.getCurrent().getSession();, eg:
UI.getCurrent().getSession().getAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY);
or
UI.getCurrent().getSession().setAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY, currentUser);
I tested this with your sample and it worked fine.
I am new to Tridion Event System. I have written a small code.
[TcmExtension("MyEventHandlerExtension")]
public class EH : TcmExtension
{
public EH()
{
Subscribe();
}
public void Subscribe()
{
//EventSystem.Subscribe<Component, DeleteEventArgs>(HandlerForInitiated, EventPhases.Initiated);
EventSystem.Subscribe<Tridion.ContentManager.CommunicationManagement.Page, Tridion.ContentManager.Extensibility.Events.PublishOrUnPublishEventArgs>(HandlerForCommitted, EventPhases.All);
}
private void HandlerForCommitted(IdentifiableObject subject, PublishOrUnPublishEventArgs args, EventPhases phase)
{
TDSE obj = new TDSE();
Tridion.ContentManager.Interop.TDS.Publication pub = obj.GetPublication("tcm:0-150-1");
Tridion.ContentManager.Interop.TDS.Page pubPage = obj.GetPage("tcm:150-12374-64", pub);
pubPage.Publish("tcm:0-1-65538", false, true, false, default(DateTime), default(DateTime), default(DateTime));
}
}
using this code i wanted to publish a page everytime when a publish and unpublish event occur.
I build this code and register its path in tridion config file .
But its not working.Please Help
Ok, first of all remove all your TDSE code, you should use TOM.NET. You can get session as subject.Session
Then make sure you have registered this extension in Tridion.ContentManager.config and restarted your system
And finally - if something doesn't work, just add simple code that will create a file in your HandlerForCommitted whenever event occurs, this way you will be able to see if your extension get executed.
The 2011 Event System uses the TOM.NET API and not the TOM API. Please do not create new TDSE objects in the 2011 Event System. Even though you can reference the old Interop libraries, there is no reason to do so with 2011. Using the TOM.NET libraries you should see better performance and also the code is future-proof.
Mihai Cadariu has a nice example where he uses TOM.NET to Publish a page from a Tridion Template. Adjusting the code to check for previewmode or publish mode and setting your own user and priority (instead of reading it from the current transaction) should work well.
Below code from http://yatb.mitza.net/2012/05/publishing-from-template-code-using.html
public void Publish(Engine engine, String tcmUri, User user, PublishPriority priority)
{
Session session = new Session(user.Title);
PublishInstruction publishInstruction = new PublishInstruction(session);
RenderInstruction renderInstruction = new RenderInstruction(session);
renderInstruction.RenderMode = RenderMode.Publish; // work around. needs to be specified for binaries.
publishInstruction.RenderInstruction = renderInstruction;
List<IdentifiableObject> items = new List<IdentifiableObject>() { session.GetObject(tcmUri) };
List<PublicationTarget> targets = new List<PublicationTarget>() { engine.PublishingContext.PublicationTarget };
PublishEngine.Publish(items, publishInstruction, targets, priority);
session.Dispose();
}
// called with
PublishTransaction currentTransaction = TemplateUtils.GetPublishTransaction(engine);
TemplateUtils.Publish(engine, itemUri, currentTransaction.Creator, currentTransaction.Priority);
Your code seems to have the three things I "normally" forget:
the class is public
it extends TcmExtension
it has a TcmExtension attribute
If you've registered the class correctly in the configuration file, it should just be a matter of restarting the relevant module(s). In this case I'd expect those to be the Publisher and TcmServiceHost services.
After restarting those modules and triggering a publish action, you should see an event being logged (in the Windows event viewer) that your extension is being loaded.
If that even shows, it means your assembly is being loaded into the relevant Tridion process and the class is being recognized and instantiated.
If at this stage your handler doesn't fire you may have to consider listening to a different event. Whenever I want to interact with the publishing, I end up listening for the SaveEventArgs of a PublishTransaction, instead of the PublishOrUnPublishEventArgs on the Page.
I wanted to run scheduling process in asp.net periodically in web application.
In brief,My database table is having date & deadline Hrs.I want to calculate expected dateTime from both then another table get updated (inserts 1000s of records) periodically & also want to run process of mail sending according to that calculation for the same.
This is expected scheduled process which should be executed periodically.
The Quartz.NET job scheduler library is excellent for this sort of thing.
You can use Window Service to work in backgroud or scheduling , please see below links:
Using Timers in a Windows Service
Here's what I did:
public class Email {
private static System.Threading.Timer threadingTimer;
public static void StartTimer()
{
if (threadingTimer == null)
threadingTimer = new Timer(new TimerCallback(Callback), HttpContext.Current, 0, 20000);
}
private static void Callback(object sender)
{
if (/* Your condition to send emails */)
using (var context = new MyEntities())
{
var users = from user in context.Usere
select user;
foreach (var user in users)
{
// Send an email to user
}
}
}
}
And you have to add this to Application_Start:
void Application_Start(object sender, EventArgs e)
{
EMail.StartTimer();
}
Check out this old article from Jeff Atwood:
Easy Background Tasks in ASP.NET
Basically he suggests that you use the cache expiration mechanism to schedule a timed task. The problem is: your web application needs to be running. What if the website isn't called at all? Well, since IIS 7.5 there is the possibility to keep your web app running at all times: auto starting web apps. Jeff suggests in the comments that his approach served well until they outgrew it. His conclusion is that for small sites this is a good approach.
Help me solve next problem.
I have ASP .NET MVC2 application. I run it on IIS 7.5. In one page user clicks button and handler for this button sends request to server (jquery.ajax). At server action in controller starts new thread (it makes long time import):
var thread = new Thread(RefreshCitiesInDatabase);
thread.Start();
State of import is available in static variable. New thread changes value of variable in the begin of work.
User can check state of import too with the help of this variable, which is used in view. And user sees import's state.
When I start this function few minutes everything is okey. On page I see right state of import, quantity of imported records is changed, I see changes in logs. But after few minutes begin troubles.
When I refresh page with import state sometimes I see that import is okey but sometimes I see page with default values about import (like application is just started), but after that again I can see page with normal import's state.
I tried to attach Visual Studio to IIS process and debug application. But when request comes to controller sometimes static variables have right values and sometimes they have default values (static int has 0, static string has "" etc.).
Tell me what I do wrong. May be I must start additional thread in other way?
Thanks in advance,
Dmitry
I add parts of code:
Controller:
public class ImportCitiesController : Controller
{
[Dependency]
public SaveCities SaveCities { get; set; }
//Start import
public JsonResult StartCitiesImport()
{
//Methos in core dll, which makes import
SaveCities.StartCitiesSaving();
return Json("ok");
}
//Get Information about import
public ActionResult GetImportState()
{
var model = new ImportCityStatusModel
{ NowImportProcessing = SaveCities.CitiesSaving };
return View(model);
}
}
Class in Core:
public class SaveCities
{
// Property equals true, when program are saving to database
public static bool CitiesSaving = false;
public void StartCitiesSaving()
{
var thread = new Thread(RefreshCitiesInDatabase);
thread.Start();
}
private static void RefreshCitiesInDatabase()
{
CitiesSaving = true;
//Processing......
CitiesSaving = false;
}
}
UPDATE
I think, I found problem, but still I don't know how solve it. My IIS uses application pool with parameter "Maximum Worker Processes" = 10. And all tasks in application are handled by few processes. And my request to controll about import's state always is handled by different processes. And they have different static variables. I guess it is right way for solving.
But I don't know how merge all static values in one place.
Without looking at the code, here are the obvious question. Are you sure your access is thread safe (that is do you properly use lock to update you value or even access it => C# thread safety with get/set) ?
A code sample could be nice.
thanks for the code, it seem that CitiesSaving is not locked properly before read/write you should hide the instance variable behind a property to handle all the locking. Marking this field as volatile could also help (see http://msdn.microsoft.com/en-us/library/aa645755(v=vs.71).aspx )