I've made this simple app for recieving sms,When I receive a message I want to output this on my TextView,upuntil now for testing I was just doing
that inside a button .You recieve a message ,click on the button and you get the sms on textview.If I try to do this without a button ,at the start of compilation
I get a null reference exception.Can anyone help me on this ?
//----------MainActivity.cs---------------
using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using Android.Content;
using Android.Telephony;
using Android.Provider;
using Android.Util;
using Java.Lang;
using System.Text.RegularExpressions;
using Xamarin.Essentials;
using System;
using Android;
using Android.Support.V4.Content;
using Android.Content.PM;
namespace Sms_Receiver2
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
public Receiver1 _receiver; // Receiver class
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneword);
Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadSms) != (int)Permission.Granted)
{
RequestPermissions(new string[] { Manifest.Permission.ReadSms, Manifest.Permission.SendSms, Manifest.Permission.ReceiveSms }, 0);
}
translateButton.Click += (s, e) =>
{};
translatedPhoneWord.Text = _receiver.message;// null reference exception
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnResume()
{
base.OnResume();
_receiver = new Receiver1();
IntentFilter filter = new IntentFilter();
filter.AddAction("android.provider.Telephony.SMS_RECEIVED");
filter.AddAction("android.provider.Telephony.SMS_DELIVER");
RegisterReceiver(_receiver, filter);
}
protected override void OnPause()
{
base.OnPause();
UnregisterReceiver(_receiver);
}
}
}
//---------Reciever.cs -------------
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Telephony;
using Android.Provider;
namespace Sms_Receiver2
{
[BroadcastReceiver(Enabled = true, Exported = true, Permission = "android.permission.BROADCAST_SMS")]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED", "android.provider.Telephony.SMS_DELIVER" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class Receiver1 : BroadcastReceiver
{
public string message, address = "";
public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent intent)
{
if (intent.HasExtra("pdus"))
{
var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
foreach (var item in smsArray)
{
var sms = SmsMessage.CreateFromPdu((byte[])item);
address = sms.OriginatingAddress;
message = sms.MessageBody;
Toast.MakeText(context, "Number :" + address + "Message : " + message, ToastLength.Short).Show();
}
}
}
}
}
Slight modification of your code works
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private SMSBroadcastReceiver _receiver;
private TextView _smsTextView; //Textview where list of received sms will show
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
_smsTextView = FindViewById<TextView>(Resource.Id.smstextview);
_receiver = new SMSBroadcastReceiver();
_receiver.SmsActionDelegate = InokeOnNewSMS;
IntentFilter filter = new IntentFilter();
filter.AddAction("android.provider.Telephony.SMS_RECEIVED");
filter.AddAction("android.provider.Telephony.SMS_DELIVER");
RegisterReceiver(_receiver, filter);
}
//this method will be invoked when new sms is received in the broadcast received
public void InokeOnNewSMS(string address, string message)
{
_smsTextView.Text += $"{address} : {message}\n\n";
}
}
[BroadcastReceiver(Enabled = true, Exported = true, Permission = "android.permission.BROADCAST_SMS")]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED", "android.provider.Telephony.SMS_DELIVER" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class SMSBroadcastReceiver : BroadcastReceiver
{
public string message = "", address = "";
public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";
public Action<string, string> SmsActionDelegate;
public override void OnReceive(Context context, Intent intent)
{
if (intent.HasExtra("pdus"))
{
var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
foreach (var item in smsArray)
{
var sms = SmsMessage.CreateFromPdu((byte[])item);
address = sms.OriginatingAddress;
message = sms.MessageBody;
SmsActionDelegate?.Invoke(address, message);
Toast.MakeText(context, "Number :" + address + "Message : " + message, ToastLength.Short).Show();
}
}
}
}
Related
I made a simple Countdowntimer app for another project , I tried my best to run this simple timer to start,pause and reset the timer.My first problem was the fact that,
Since a MainActivity cannot inherit multiple classes I had to make a new one just so I can Inherit the abstract class CountDownTimer,Secondly I do not know completely that I was able to call the CountDownTimer constructor from the abstract class because I cannot intialize an abstract class only call it form within the subclass constructor .Also , I dont understand how do I wire it up with my UI.I'm completely lost in this, Can anyone help me on this?? .I have also published the code on github
GitHub : https://github.com/owais19m/TimerApp_Test
Thanks ,
Blockquote
using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using Android.Content;
using Android.Telephony;
using Android.Provider;
using Android.Util;
using Java.Lang;
using System.Text.RegularExpressions;
using Xamarin.Essentials;
using System;
using Android;
using Android.Support.V4.Content;
using Android.Content.PM;
namespace TimerApp_Test
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private static System.Boolean mTimerRunning;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
//------------ Views -------------
Button ResetBtn = FindViewById<Button>(Resource.Id.ResetButton);
Button StartBtn = FindViewById<Button>(Resource.Id.StartButton);
TextView TimerText = FindViewById<TextView>(Resource.Id.CountdownText);
//--------------------------------
StartBtn.Click += (s, e) =>
{
if (mTimerRunning)
{
pauseTimer();
}
else
{
startTimer();
}
};
ResetBtn.Click += (s, e) =>
{
resetTimer();
};
}
public void startTimer()
{
CountDown1 Coutdwn = new CountDown1(6000,1000);
Coutdwn.OnTick(1000);
Coutdwn.Start();
mTimerRunning = true;
}
public void resetTimer()
{
}
public void pauseTimer()
{
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public class CountDown1 : CountDownTimer
{
public static long Start_Time_Milliseconds = 600000;
public static CountDownTimer mcountDownTimer;
public static long mTimeLeftInMillis = Start_Time_Milliseconds;
public CountDown1(long mTimeLeftInMilli, long countDownInterva) : base(mTimeLeftInMilli,countDownInterva)
{
}
public override void OnFinish() { }
public override void OnTick(long millisUntilFinished)
{
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
}
public string updateCountDownText()
{
int minutes = (int)mTimeLeftInMillis / 1000 / 60;
int seconds = (int)mTimeLeftInMillis / 1000 % 60;
string timeLeftFormatted = string.Format("%02d:%02d", minutes, seconds);
return timeLeftFormatted;
}
public void Cancellation()
{
mcountDownTimer.Cancel();
}
}
}
Blockquote
You could pass the TextView which you would display the time as the parameter into your custom CountDownTimer like below:
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
CountDown1 Coutdwn;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
//------------ Views -------------
Button ResetBtn = FindViewById<Button>(Resource.Id.ResetButton);
Button StartBtn = FindViewById<Button>(Resource.Id.StartButton);
TextView TimerText = FindViewById<TextView>(Resource.Id.CountdownText);
Coutdwn = new CountDown1(60000, 1000, TimerText);
//--------------------------------
StartBtn.Click += (s, e) =>
{
startTimer();
};
ResetBtn.Click += (s, e) =>
{
resetTimer();
};
}
public void startTimer()
{
Coutdwn.Start();
}
public void resetTimer()
{
myTimer.Cancel();
myTimer.Start();
}
public void pauseTimer()
{
myTimer.Cancel();
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public class CountDown1 : CountDownTimer
{
TextView timeTextView;
public CountDown1(long mTimeLeftInMilli, long countDownInterva,TextView textView) : base(mTimeLeftInMilli,countDownInterva)
{
timeTextView = textView;
}
public override void OnFinish() { }
public override void OnTick(long millisUntilFinished)
{
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
}
public void updateCountDownText()
{
int minutes = (int)mTimeLeftInMillis / 1000 / 60;
int seconds = (int)mTimeLeftInMillis / 1000 % 60;
string timeLeftFormatted = string.Format("%02d:%02d", minutes, seconds);
timeTextView.Text = timeLeftFormatted;
}
}
Thanks, This worked great ,just regarding this, I coded a simple notification program when my timer stops in OnFinished() method in the CountDown1 class ,I get a "Java.Lang.IllegalStateException: 'System services not available to Activities before onCreate()' " error ,is there a work around for this ?
public NotificationCompat.Builder builder;
MainActivity activity = new MainActivity();
NotificationManagerCompat notificationManager;
public override void OnFinish()
{
Toast.MakeText(Application.Context ,"Finished",ToastLength.Short).Show();
builder = new NotificationCompat.Builder(this.activity, CHANNEL_ID).SetAutoCancel(true)
.SetContentTitle("CountDownTimer !!")
.SetSmallIcon(Resource.Drawable.abc_ic_star_black_48dp)
.SetContentText($" Stopped"); // display.
notificationManager = NotificationManagerCompat.From(this.activity); Error // Java.Lang.IllegalStateException: 'System services not available to Activities...
notificationManager.Notify(NOTIFICATION_ID, builder.Build());
}
i have xamarin android application that read from clipboard and write to it. it uses foreground services if the user hit the button. the problem is when the user hit the button again the services disappear from running services but still doing it's job (editing copied text). how can i completely stop it from working?
foreground.cs:
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Clipboard.ClipboardContentChanged += async (o, e) =>
{
var text = await Clipboard.GetTextAsync();
Toast.MakeText(this, text, ToastLength.Long).Show();
if (text.Contains("#"))
{
await Clipboard.SetTextAsync(text.Replace("#", ""));
}
};
Notification notif = ReturnNotif();
StartForeground(1, notif);
return StartCommandResult.NotSticky;
}
public override void OnDestroy()
{
base.OnDestroy();
}
public override void OnCreate()
{
base.OnCreate();
}
public override bool StopService(Intent name)
{
StopForeground(true);
StopSelf();
return base.StopService(name);
}
MainActivity.cs:
if (id == Resource.Id.myService)
{
if (count != 1)
{
count = 1;
var intent = new Intent(this, typeof(foreground));
intent.SetAction("No");
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
StartForegroundService(intent);
}
else
{
StartService(intent);
}
}
else
{
var intent = new Intent(this,typeof(foreground));
StopService(intent);
Toast.MakeText(this, "Service Stopped", ToastLength.Long).Show();
count = 0;
}
}
what i am doing wrong ?
Edit :
Service will completely stops if the app is removed from recently used apps.
In your MyForegroundService.cs. Just add StopForeground(true) in OnDestroy() method like following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace ForegroundServiceDemo
{
[Service]
class MyForegroundService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
CreateNotificationChannel();
string messageBody = "service starting";
// / Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this,typeof(Activity1));
// Create the TaskStackBuilder and add the intent, which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
var notification = new Notification.Builder(this, "10111")
.SetContentIntent(resultPendingIntent)
.SetContentTitle("Foreground")
.SetContentText(messageBody)
.SetSmallIcon(Resource.Drawable.main)
.SetOngoing(true)
.Build();
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
//do you work
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
base.OnDestroy();
StopForeground(true);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channelName = Resources.GetString(Resource.String.channel_name);
var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel("10111", channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
When you want to stop it. Just call following code.
Android.App.Application.Context.StopService(intent);
Here is my code in the Activity.
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button button1 = FindViewById<Button>(Resource.Id.button1);
Button button2 = FindViewById<Button>(Resource.Id.button2);
button2.Click += Button2_Click;
button1.Click += Button1_Click;
}
Intent intent;
private void Button2_Click(object sender, System.EventArgs e)
{
// stop foreground service.
Android.App.Application.Context.StopService(intent);
}
private void Button1_Click(object sender, System.EventArgs e)
{
intent = new Intent(Android.App.Application.Context, typeof(MyForegroundService));
// start foreground service.
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
StartForegroundService(intent);
}
}
Here is running GIF.
====Update====
the expected behavior is : when service stopped user can copy and paste normally without the service interference
You can use following way to achieve that.Use Clipboard.ClipboardContentChanged += Clipboard_ClipboardContentChanged; to execute the behavior, use Clipboard.ClipboardContentChanged -= Clipboard_ClipboardContentChanged; to disable the behavior in the OnDistory method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Essentials;
namespace ForegroundServiceDemo
{
[Service]
class MyForegroundService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
CreateNotificationChannel();
string messageBody = "service starting";
Clipboard.ClipboardContentChanged += Clipboard_ClipboardContentChanged;
// / Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this,typeof(Activity1));
// Create the TaskStackBuilder and add the intent, which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
var notification = new Notification.Builder(this, "10111")
.SetContentIntent(resultPendingIntent)
.SetContentTitle("Foreground")
.SetContentText(messageBody)
.SetSmallIcon(Resource.Drawable.main)
.SetOngoing(true)
.Build();
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
//do you work
return StartCommandResult.Sticky;
}
private async void Clipboard_ClipboardContentChanged(object sender, EventArgs e)
{
//throw new NotImplementedException();
var text = await Clipboard.GetTextAsync();
Toast.MakeText(this, text, ToastLength.Long).Show();
if (text.Contains("#"))
{
await Clipboard.SetTextAsync(text.Replace("#", ""));
}
}
public override void OnDestroy()
{
base.OnDestroy();
Clipboard.ClipboardContentChanged -= Clipboard_ClipboardContentChanged;
StopForeground(true);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channelName = Resources.GetString(Resource.String.channel_name);
var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel("10111", channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
Here is run GIF.
To prevent this issues, add a "myServiceIsRunning" bool value in the Properties dictionary when you start your foreground method like this:
Application.Current.Properties["myServiceIsRunning"] = true
With a get function or whatever you want, before start the foreground method, verify if the key "myServiceIsRunning" exist, and if it exist, how is his status:
public bool getRunningStateMyService(){
bool myServiceIsRunningValue;
if (Application.Current.Properties.ContainsKey("myServiceIsRunning"))
{
myServiceIsRunningValue = Convert.ToBoolean(Application.Current.Properties["myServiceIsRunning"]);
}
else
{
myServiceIsRunningValue = false;
}
return locationServiceIsRunning;
}
After you get the value, with a simple if{}/else{}, you can choose to start a new instance or not if you're service is running or not. Or, in you're case just prevent the foreground method continue to run.
Don't forget to set your value to false when you destroy the foreground method.
the Properties dictionary can store data trought closing app to. you can have more infos here:
https://learn.microsoft.com/fr-fr/xamarin/xamarin-forms/app-fundamentals/application-class#Properties_Dictionary
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Plugin.Media;
using Refractored.Controls;
using Uber_Driver.Activities;
namespace Uber_Driver.Fragments
{
public class AccountFragment : Android.Support.V4.App.Fragment
{
ImageView profileImage;
Button logoutButton;
readonly string[] permissionGroup =
{
Manifest.Permission.ReadExternalStorage,
Manifest.Permission.WriteExternalStorage,
Manifest.Permission.Camera
};
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
View view = inflater.Inflate(Resource.Layout.account, container, false);
profileImage = (ImageView)view.FindViewById(Resource.Id.profileImage);
profileImage.Click += ProfileImage_Click;
logoutButton = (Button)view.FindViewById(Resource.Id.LogoutButton);
logoutButton.Click += LogoutButton_Click;
return view;
}
private void ProfileImage_Click(object sender, EventArgs e)
{
Android.Support.V7.App.AlertDialog.Builder photoAlert = new Android.Support.V7.App.AlertDialog.Builder(Android.App.Application.Context);
photoAlert.SetMessage("Change Photo");
photoAlert.SetNegativeButton("Take Photo", (thisalert, args) =>
{
//capture
TakePhoto();
});
photoAlert.SetPositiveButton("Upload Photo", (thisAlert, args) =>
{
// Choose Image
SelectPhoto();
});
photoAlert.Show();
}
async void TakePhoto()
{
await CrossMedia.Current.Initialize();
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium,
CompressionQuality = 20,
Directory = "Sample",
Name = GenerateRadomString (6) + "profileImage.jpg"
});
if (file == null)
{
return;
}
//Converts file.path to byte array and set the resulting bitmap to imageview
byte[] imageArray = System.IO.File.ReadAllBytes(file.Path);
Bitmap bitmap = BitmapFactory.DecodeByteArray(imageArray, 0, imageArray.Length);
profileImage.SetImageBitmap(bitmap);
}
async void SelectPhoto()
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
Toast.MakeText(Android.App.Application.Context, "Upload not supported", ToastLength.Short).Show();
return;
}
var file = await CrossMedia.Current.PickPhotoAsync(new Plugin.Media.Abstractions.PickMediaOptions
{
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium,
CompressionQuality = 30,
});
if (file == null)
{
return;
}
byte[] imageArray = System.IO.File.ReadAllBytes(file.Path);
Bitmap bitmap = BitmapFactory.DecodeByteArray(imageArray, 0, imageArray.Length);
profileImage.SetImageBitmap(bitmap);
}
string GenerateRadomString(int length)
{
Random rand = new Random();
char[] allowchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".ToCharArray();
string sResult = "";
for (int i = 0; i <= length; i++)
{
sResult += allowchars[rand.Next(0, allowchars.Length)];
}
return sResult;
}
private void LogoutButton_Click(object sender, EventArgs e)
{
StartActivity(new Intent(Application.Context, typeof(LoginActivity)));
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
I have tried to get profileImage click to allow the user to set up the profile image, but at whenever i click the image in the the app, nothing is showing up.At some point the app fail to respond. what could be the problem. I have installed all the plugin needed and done all I think was expected.
I have also realized that some issues reflects in my code in visual studio as attached picture.
enter image description here
First,check your Activity,Whetherit has the attribute Theme.
[Activity(Label = "#string/app_name", Theme = "#style/MyTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
you could define a theme in your Resources/values/styles.xml:
<resources>
<!-- Base application theme. -->
<style name="MyTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorAccent">#color/colorAccent</item>
...
</style>
Second,if your activity extends AppCompatActivity,you should use the theme theme.appcompat.xxx
Update :
try to change
Android.Support.V7.App.AlertDialog.Builder photoAlert = new Android.Support.V7.App.AlertDialog.Builder(Android.App.Application.Context);
to
Android.Support.V7.App.AlertDialog.Builder photoAlert = new Android.Support.V7.App.AlertDialog.Builder(Activity);
Helo I am working on adding an assist feature to my app that when the user holds down on the home button an android activity opens with cards that the user can click on that then opens the xamarin forms page in question for example when the math card is clicked the MathPage xamarin forms page opens this works but if I have the xamarin forms app running in the background it loads the home screen layout regardless of what button i click. If I close the xamarin forms app from multitasking and hold down on the home button and click on the math card it will open the MathPage.
heres my android Activity code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms.Platform.Android;
namespace Appname.Droid
{
[Activity(LaunchMode = LaunchMode.SingleInstance, Theme = "#style/Theme.Transparent")]
[IntentFilter(new[] { Intent.ActionAssist }, Categories = new[] { Intent.CategoryDefault })]
public class ToolBelt : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.ToolBelt);
}
//Code That Opens The Math Part!
[Java.Interop.Export("math")] // The value found in android:onClick attribute.
public void btnOneClick4(View v) // Does not need to match value in above attribute.
{
var intent = new Intent(ApplicationContext, typeof(MainActivity));
intent.PutExtra("page", "Math");
StartActivity(intent);
}
//Code That Opens The Science Part!
[Java.Interop.Export("science")] // The value found in android:onClick attribute.
public void btnOneClick9(View v) // Does not need to match value in above attribute.
{
var intent = new Intent(ApplicationContext, typeof(MainActivity));
intent.PutExtra("page", "Science");
StartActivity(intent);
}
//Code That Opens The Handwriting Part!
[Java.Interop.Export("english")] // The value found in android:onClick attribute.
public void btnOneClick10(View v) // Does not need to match value in above attribute.
{
var intent = new Intent(ApplicationContext, typeof(MainActivity));
intent.PutExtra("page", "Handwriten");
StartActivity(intent);
}
//Code That Opens The Flascards Part!
[Java.Interop.Export("flashcard")] // The value found in android:onClick attribute.
public void btnOneClick11(View v) // Does not need to match value in above attribute.
{
var intent = new Intent(ApplicationContext, typeof(MainActivity));
intent.PutExtra("page", "Flashcards");
StartActivity(intent);
}
//Code That Opens The Internet App!
[Java.Interop.Export("web")] // The value found in android:onClick attribute.
public void btnOneClick8(View v) // Does not need to match value in above attribute.
{
var uri = Android.Net.Uri.Parse("http://www.google.com");
var intent = new Intent(Intent.ActionView, uri);
StartActivity(intent);
}
//Code That Opens The Gmail App!
[Java.Interop.Export("email")] // The value found in android:onClick attribute.
public void btnOneClick3(View v) // Does not need to match value in above attribute.
{
var intent = PackageManager.GetLaunchIntentForPackage("com.google.android.gm");
StartActivity(intent);
}
//Code That Opens The Books App!
[Java.Interop.Export("books")] // The value found in android:onClick attribute.
public void btnOneClick5(View v) // Does not need to match value in above attribute.
{
var intent = PackageManager.GetLaunchIntentForPackage("com.google.android.apps.books");
StartActivity(intent);
}
}
}
here's the MainActivity droid code:
using System;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Collections.Generic;
using AppName.Droid;
using AppName.Data;
[assembly: Xamarin.Forms.Dependency(typeof(MainActivity))]
namespace AppName.Droid
{
[Activity(Label = "AppName", Icon = "#drawable/ic_launcher", Theme = "#style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, SchoolTools.PackageInterface
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
var page = Intent.GetStringExtra("page");
LoadApplication(new App(page));
}
public IList<Apps> GetInstalledApps()
{
IList<Apps> apps = new List<Apps>();
var pkgInfos = global::Xamarin.Forms.Forms.Context.PackageManager.GetInstalledPackages(PackageInfoFlags.Activities);
foreach(var pi in pkgInfos)
{
// skip system packages
if (pi.ApplicationInfo.DataDir.StartsWith("/data/user/"))
{
Apps app = new Apps(pi.ApplicationInfo.LoadLabel(global::Xamarin.Forms.Forms.Context.PackageManager).ToString(), pi.PackageName);
if (!apps.Contains(app))
{
apps.Add(app);
}
}
}
return apps;
}
public bool Launch(string package)
{
var intent = Application.Context.PackageManager.GetLaunchIntentForPackage(package);
bool retVal = IsIntentAvailable(intent);
if (retVal)
{
intent.AddFlags(ActivityFlags.NewTask);
Application.Context.StartActivity(intent);
}
return retVal;
}
private static bool IsIntentAvailable(Intent intent)
{
return intent != null && Application.Context.PackageManager.QueryIntentActivities(intent, 0).Count != 0;
}
}
}
heres my app.cs code:
using System;
using Xamarin.Forms;
namespace AppName
{
public class App : Application
{
public App(string pageName = "AppNameHome")
{
switch (pageName)
{
case "Math":
MainPage = new NavigationPage(new MathPage());
break;
case "Science":
MainPage = new NavigationPage(new Science.ScienceToolsPage());
break;
case "Handwriten":
MainPage = new NavigationPage(new Handwriting.HandwritingToolsPage());
break;
case "Flashcards":
MainPage = new NavigationPage(new Flashcards.FlashCardHome());
break;
default:
MainPage = new NavigationPage(new AppNameHome());
break;
}
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
any help would be amazing!
Thanks in advance :)
I figured out the problem i needed to add SingleInstance to the main activity as well is nohistory = true heres the code needed to fix this issue:
[Activity(LaunchMode = LaunchMode.SingleInstance, NoHistory = true,
Label = "AppName", Icon = "#drawable/ic_launcher", Theme = "#style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
I want to get the user's current location (latitude and longitude) always using Sim-based network only, not by using any other networks (like WiFi, Mobile Data, GPS and other Network and even all these are in Disabled mode in mobile). Not necessarily exact location but even approximate location.
Is there any possibility to get it? If any of you can explain and include code; I searched in Google but did not get the correct related answer.
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Locations;
using Android.Util;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Xml.Linq;
using System.Threading;
namespace GPS_Android
{
[Activity(Label = "GPS_Android", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity,ILocationListener
{
private Location _currentLocation;
private LocationManager _locationManager;
private TextView _locationText;
private TextView _addressText;
private string _locationProvider;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
_addressText = FindViewById<TextView>(Resource.Id.address_text);
_locationText = FindViewById<TextView>(Resource.Id.location_text);
FindViewById<TextView>(Resource.Id.get_address_button).Click += AddressButton_OnClick;
InitializeLocationManager();
}
public void InitializeLocationManager()
{
_locationManager = (LocationManager)GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = String.Empty;
}
}
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
async void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
_addressText.Text = "Can't determine the current location.";
return;
}
Geocoder geocoder = new Geocoder(this);
IList<Address> addressList = await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10);
Address address = addressList.FirstOrDefault();
if (address != null)
{
StringBuilder deviceAddress = new StringBuilder();
for (int i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceAddress.Append(address.GetAddressLine(i))
.AppendLine(",");
}
_addressText.Text = deviceAddress.ToString();
}
else
{
_addressText.Text = "Unable to determine the address.";
}
}
public void OnLocationChanged(Location location)
{
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location.";
}
else
{
_locationText.Text = String.Format("{0},{1}", _currentLocation.Latitude, _currentLocation.Longitude);
}
}
public void OnProviderDisabled(string provider) { }
public void OnProviderEnabled(string provider) { }
public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
}
}
You can use LocationManager.NETWORK_PROVIDER to get Latitude and Longitude without opening GPS
btnNWShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Location nwLocation = appLocationService
.getLocation(LocationManager.NETWORK_PROVIDER);
if (nwLocation != null) {
double latitude = nwLocation.getLatitude();
double longitude = nwLocation.getLongitude();
Toast.makeText(
getApplicationContext(),
"Mobile Location (NW): \nLatitude: " + latitude
+ "\nLongitude: " + longitude,
Toast.LENGTH_LONG).show();
} else {
showSettingsAlert("NETWORK");
}
}
});