This seems to be a simple task, but I`m failing to do it. Saw a bunch of tutorials and stuff. Maybe someone can help me.
I'm starting from a Xamarin Forms App, that will have a task specific for Android (Targeting Android 8.0 - Oreo).
So to test I've made as follow (XF 3.2.0.839982). Told this mainly because it don't have a OnResume, OnPause, On....methods...(or I don't know about them).
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, Application.IActivityLifecycleCallbacks
{
SMSBroadcastReceiver myreceiver;
IntentFilter intentFilter;
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var buttonbtnsendmessage = (Button)FindViewById(Resource.Id.sendBroadcast);
myreceiver = new SMSBroadcastReceiver();
intentFilter = new IntentFilter(SMSBroadcastReceiver.IntentAction);
intentFilter.Priority = 1000;
RegisterReceiver(myreceiver, intentFilter);
}
}
public class SMSBroadcastReceiver : BroadcastReceiver
{
public static string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent i)
{
if (i.Action != IntentAction)
{
return;
}
Toast.MakeText(context, "Received broadcast in MyBroadcastReceiver, " +
" value received: " + i.GetStringExtra("key"),
ToastLength.Long).Show();
}
}
and Manifest
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.BROADCAST_SMS" />
But it do not fall in my receiver when I get a SMS.
Just to check if it would work at all, I changed the IntentAction to "MY_TEST", and sent the broadcast from another app, and it was able to Toast.
Any Ideas?
Xamarin Forms - SMS BroadcastReceiver in Android failing to work
You are missing a lot is in your code.
Requesting Runtime Permissions in Android Marshmallow +
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. You should request permissions at runtime.
System permissions are divided into two categories, normal and dangerous:
Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically.
Dangerous permissions can give the app access to the user's confidential data. If you list a dangerous permission, the user has to explicitly give approval to your app during the runtime of the app.
READ_SMS is categorized as Dangerous permissions, so you should check this permissions manually for API level 23 and above.
Adorn BroadcastReceiver with the BroadcastReceiverAttribute
For more detail information, please refer to the official document: Broadcast Receivers in Xamarin.Android
Here is an example:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" })]
class SMSBroadcastReceiver: BroadcastReceiver
{
public static string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent i)
{
if (i.Action != IntentAction)
{
return;
}
Toast.MakeText(context, "Received broadcast in MyBroadcastReceiver, " +
" value received: " + i.GetStringExtra("key"),
ToastLength.Long).Show();
}
}
Related
I have a background service in android.
My code is as follows:
[Service]
public class PeriodicService : Service
{
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Device.StartTimer(TimeSpan.FromSeconds(5), () =>
{
// code
});
return StartCommandResult.Sticky;
}
}
The MainActivity class:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
StartService(new Intent(this, typeof(PeriodicService)));
}
Permission AndroidManifest.xml:
<uses-permission android:name="android.permission.PeriodicService" />
The problem is that my service only works in the background when the app is active or in the foreground but when I close the app it doesn't run in the background.
A possible solution is to follow along with what Fabio has written in his post about how to create The Never Ending Background Task.
The idea behind this is to create a BroadcastReceiver and Android Service in the manifest. The BroadcastReceiver will then activate the service with foreground priority as the application is being closed. If you are dealing with post Android 7 then he created an update to his blog showing The Fix.
Just to get a better understanding of how basic Android services operate, I'd recommend taking a look at this Android Services Tutorial
I also saw this other StackOverflow post that seems to be pretty similar so maybe there will be some useful info over there too.
I'm not too acclimated in this stuff, but I was able to follow along with the blog posts pretty easily so I hope this ends up helping :). If anyone finds a better solution I'd love to hear about it so tag be (if you would be so kind) so I can stay updated!
Have a Xamarin forms project and trying to hook in NFC reading to the app. Currently plumbing in the iOS native side of things. I've setup all the provisioning and options on the apple portal side of things and i've added the following to the entitlements:
<dict>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>NDEF</string>
</array>
</dict>
Also added to the info.plist:
<key>NFCReaderUsageDescription</key>
<string>NFC tag to read NDEF messages into the application</string>
The code i've got for my native dependency for iOS is as follows:
[assembly: Dependency(typeof(RFIDScannerHelper))]
namespace MyProject.Mobile.Platform.iOS
{
public class RFIDScannerHelper : IRFIDScannerHelper
{
public bool hasRFID()
{
return true;
}
NFCNdefReaderSession Session;
public void ScanRFID(Action<string> act, VisualElement el)
{
NFChecker nfchecker = new NFChecker();
Session = new NFCNdefReaderSession(nfchecker, null, false);
Session?.BeginSession();
}
}
public class NFChecker : NSObject, INFCNdefReaderSessionDelegate
{
public Action<string> nfcFoundAction;
public void DidDetect(NFCNdefReaderSession session, NFCNdefMessage[] messages)
{
foreach (NFCNdefMessage msg in messages)
{
if (msg.Records.Count() > 0)
{
nfcFoundAction.Invoke(new NSString(msg.Records[0].Payload, NSStringEncoding.UTF8));
}
}
}
public void DidInvalidate(NFCNdefReaderSession session, NSError error)
{
var readerError = (NFCReaderError)(long)error.Code;
if (readerError != NFCReaderError.ReaderSessionInvalidationErrorFirstNDEFTagRead &&
readerError != NFCReaderError.ReaderSessionInvalidationErrorUserCanceled)
{
}
}
}
}
When this runs it all seems to fire correctly but on start of session it goes straight to the DidInvalidate method in the ReaderDelegate and the error says "Session is invalidated unexpectedly".
Can anyone tell me what I could be missing out?
UPDATE
I've also tried the xamarin provided sample here. But I also receive the exact same error "Session is invalidated unexpectedly". I've mucked around with our provisioning but no combination changes this error. Has anyone even got the xamarin sample to work?
#matt, it's a Visual Studio 2019 error. You should select the Entitlements.plist in your project settings, but you are not able because the "entry" where you should insert the path is always disabled. I have reported the problem
https://developercommunity.visualstudio.com/content/problem/752711/xamarinios-i-cant-set-entitlements.html
A while back, I had a crash course on Advanced Android, where the instructor taught about Firebase. Although, I don't remember the details, he said we could control our apps' behavior from Firebase console (e.g. by calling a Cloud function?). For example, then I can get a trigger in my app and in response, I can decide whether to serve certain functions and features to the user or not (like remove an onClickListener from a button) based on e.g. they have paid the project price or subscription fee.
Is it possible to do using Firebase?
After some research and experiment I was able to implement this functionality into my app.
First you need to add Firebase Messaging to your project. Then, create a subclass of FirebaseMessagingService. Inside the class, implement onMessageReceived, where you can access messages received from server:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.d(TAG, "onNewToken: " + s);
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG, "onMessageReceived: " + remoteMessage.getData());
Log.d(TAG, "onMessageReceived: activation: "+ remoteMessage.getData().get(Constants.ACTIVATION_KEY));
boolean activation = Boolean.valueOf(remoteMessage.getData().get(Constants.ACTIVATION_KEY));
//Save in preferences
SharedPreferences prefs = getApplication().getSharedPreferences(Constants.PREFERENCE_FILE, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(Constants.ACTIVATION_KEY, activation);
editor.apply();
}
}
Make sure you add this service in your Manifest file:
<service android:name="me.mehdi.utils.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
In your Firebase Console select Cloud Messaging from the left and hit "New message". While composing a new message, you'll notice a section "Advanced options" in addition to message text and message label. Under Advanced options, you can enter key-value pairs and send to the device you select from the dropdown menu and finally hit Send message. In your onMessageReceived method, you can read the key-value pair and update your app's shared preferences to activate or deactivate certain features.
I am trying to use Google Sign-In for my android app from here.
I am able to log-in succesfully with the google account & able to fetch all the details. However, when ever I try to logout it fails with following error :
java.lang.IllegalStateException: GoogleApiClient is not connected yet.
I have read many answers suggesting to create googleClientApi object inside onCreate() and that's what I am doing.I have added callbacks for connected and suspended but the connect never goes into suspended mode.
Following is my code snippet :
public static void doInit(Context ctx, FragmentActivity fragmentActivity) {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(
GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(ctx)
.enableAutoManage(fragmentActivity , googleAuth)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(googleAuth)
.build();
}
public static Intent doGoogleLogIn() {
return Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
}
public static boolean doGoogleLogOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
}
});
return true;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
Log.d("Signin", "onConnectionFailed:" + connectionResult);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
System.out.println("Connected...");
}
#Override
public void onConnectionSuspended(int i) {
System.out.println("Suspened....");
}
The only thing that is doubtful to me is, when I login and create googleApiClient object, its created from different activity that the one which I am using for logout. I don't suspect this is the reason because when the activity loaded, the isConnected on googleApiClient is returning true. However, the moment I do some UI action(Click on Logout), it starts returning false.
Primary requirement was to login and logout from different activities.
Finally I managed to make it work.
The actual cause of the error is "enableAutoManage" invocation at the time of Building Client object.
The API doc here suggests that it would automatically do the life cycle management by calling methods on onStart & onStop of the activity.
Therefore, if you want to use the same object across different activities then you should avoid calling "enableAutoManage" and invoke apiObject.connect(preferably in onStart of activity) and apiObject.disconnect() or logout (preferably in onStop of activity) manually.
I have a web application using Kerberos to access an external resource useing ASP.NET 3.5 and IIS.
When a user connects with the application, Kerberos authentication auto-magically allows me to connect to external resources acting as the user using delegation. This was not easy to do. It is nice, but I've a problem. Sometimes I need to connect to an external resource using an account with more rights than the user. The service account which the app-pool is running under has the addition rights I need. How can I remove the user's Kerberos identification and connect with Kerberos using the service account running the application pool?
UPDATE
I'm not sure why I am getting no responses at all. I've never seen that before. Please post questions, they may clarify the problem (to me too).
Woring in Kerberos and need an overview of delegation? Read the first part of this answer: https://stackoverflow.com/a/19103747/215752.
I have a class:
public class ProcessIdentityScope : IDisposable
{
private System.Security.Principal.WindowsImpersonationContext _impersonationContext;
private bool _disposed;
public ProcessIdentityScope()
{
_impersonationContext = System.Security.Principal.WindowsIdentity.Impersonate(IntPtr.Zero);
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
_impersonationContext.Undo();
_impersonationContext.Dispose();
_disposed = true;
}
else
throw new ObjectDisposedException("ProcessIdentityScope");
}
#endregion
}
And I use it like so:
using(ProcessIdentityScope identityScope = new ProcessIdentityScope())
{
// Any code in here runs under the Process Identity.
}
This code is based on this MSDN article: http://msdn.microsoft.com/en-us/library/ms998351.aspx