onActivityResult not being called when Preference Fragment calls it as a parent - onactivityresult

My app records GNSS positions as a tool to produce Orienteering's map using a cell phone. The main activity does all the job and when the mapper needs to export the field job done, app calls a child activity (Save_File) responsible to save on Documents/Oribooklet directory a file, using gpx format. Because of getExternalStoragePublicDirectory obsolescence, SAF is the way to choose to go. I am not an IT guy, I did this for fun, that is why I am so late with this matter: users drop me messages saying they couldn't save the field job anymore.
Main: Oribooklet
public class Oribooklet extends AppCompatActivity {
...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Mapper clicked on a menu option in the app bar overflow menu
Intent intent;
switch (item.getItemId()) {
// Respond to a click on the "Save" menu option
case R.id.action_saveFile:
// Call the Save_File Class
// Prepare to show Save UI
// Save to Shared Preference
SharedPreferences sharedPref = getSharedPreferences("user_preferences", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean("bShowSaveUI", true);
editor.apply();
intent = new Intent(Oribooklet.this, Save_File.class);
startActivity(intent);
return true;
// Respond to a click on the "Preference" menu option
case R.id.action_settings:
// Call the Class Activity_Preference for options menu
intent = new Intent(Oribooklet.this,Activity_Preference.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
Inside Save_File activity I implemented and it worked fine: when the mapper push Save, startActivityForResult is triggered, then an Android file picker starts, mapper choose where to save.
void createExternalStoragePublicDocument(String fileName) {
try {
// Call SAF
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(INTENT_TYPE);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
// https://stackoverflow.com/questions/6147884/onactivityresult-is-not-being-called-in-fragment
startActivityForResult(intent, CREATE_REQUEST_CODE);
} catch (Exception excep) {
excep.printStackTrace();
}
}
Then onActivityResult gets the returned Uri to complete the job by filling the file with the data collected on the field. Couldn't be any better!
#Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
Uri currentUri = null;
if (resultCode == Activity.RESULT_OK) {
if (requestCode == CREATE_REQUEST_CODE) {
if (resultData != null) {
currentUri = resultData.getData();
// Write contents
writeFileContent(currentUri, fileData);
}
} else if (requestCode == OPEN_REQUEST_CODE) {
if (resultData != null) {
currentUri = resultData.getData();
sendByMail(stringEMailAddress, stringSubject, currentUri);
// Back to Oribooklet
finish();
}
}
}
}
The app has a Preference fragment to set up some parameters. One of them is the standard to be used. Two standards must not be mixed doing a map. When the mapper changes the map's type, Preference used to call Save_File to do the job so no mix of data happens. It used to work fine.
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
final String key) {
// Find the one that changed and address it
Preference connectionPref = findPreference(key);
switch (key){
case "list_iof":
// IOF´s element set
SharedPreferences preferences = getActivity().getSharedPreferences("user_preferences", MODE_PRIVATE);
// Update preference Summary
ListPreference listIOFPreference = (ListPreference) findPreference("list_iof");
CharSequence iof = listIOFPreference.getEntry();
connectionPref.setSummary(getResources().getString(R.string.pref_iof_summary_1) +
iof + "\" " +
getResources().getString(R.string.pref_iof_summary_2));
// Save the field job to avoid IOF set mixing
Intent intent = new Intent(getActivity(), Save_File.class);
startActivity(intent);
break;
After SAF, the onActivityResult of Save_File is never triggered, startActivityForResult triggers the file provider but when the mapper chooses the place to save, instead of onActivityResult of Save_File it returns to Preference so the file is created empty.
I did many tests, debugging with many breaking points, setting and removing super in quite a few places, checked all S.O. posts about the matter without success.
Any idea?
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_oribooklet_v0"
android:name=".MyAppContext"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<!--android:requestLegacyExternalStore="true" -->
<!-- android:roundIcon="#mipmap/ic_oribooklet_v2"-->
<activity android:name="com.hbcavalcanti.oribooklet.Oribooklet"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- A child of the main activity -->
<activity
android:name=".Save_File"
android:label="#string/action_saveFile"
android:parentActivityName=".Oribooklet" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".Oribooklet" />
</activity>
<activity
android:name=".Activity_Preference"
android:label="#string/action_settings"
android:parentActivityName=".Oribooklet" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".Oribooklet" />
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.hbcavalcanti.oribooklet.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
</application>

When called from Preference, the Save File method used not to make any UI call, then its onActivityResult was never called.
Just for test purpose, I introduced one onActivityResult on Preference fragment and it received a trigger. I removed after the test.
I fixed the issue by also calling an UI inside Save File when Preference invoque it. This trigger its onActivityResult making everything works fine like being called from its parent.

Related

How to detect a change in Hardware(sim Change) using Xamarin

How to access event when sim card is changed in mobile(Xamarin)?
I have searched and got References in android(Java) I even tried this example
But its not triggering . Can I get any link related to Xamarin ?.
You can use this simple code to detect SIM changes.
Add new class file to your Android project SimStateChangedReceiver.cs
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "android.intent.action.SIM_STATE_CHANGED"}, Priority = (int)IntentFilterPriority.HighPriority)]
public class SimStateChangedReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent0)
{
Toast.MakeText(Application.Context, "Sim state has been changed", ToastLength.Long).Show();
}
}
Also provide READ_PHONE_STATE permission in your manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
When you change SIM in your phone OnReceive method will fire.

OnAppearing different on iOS and Android

I have found that on iOS, OnAppearing is called when the page literally appears on the screen, whereas on Android, it's called when it's created.
I'm using this event to lazily construct an expensive to construct view but obviously the Android behaviour defeats this.
Is there some way of knowing on Android when a screen literally appears on the screen?
You can use the event:
this.Appearing += YourPageAppearing;
Otherwise, you should use the methods of the Application class that contains the lifecycle methods:
protected override void OnStart()
{
Debug.WriteLine ("OnStart");
}
protected override void OnSleep()
{
Debug.WriteLine ("OnSleep");
}
protected override void OnResume()
{
Debug.WriteLine ("OnResume");
}
On Android, Xamarin.Forms.Page.OnAppearing is called immediately before the page's view is shown to user (not when the page is "created" (constructed)).
If you want an initial view to appear quickly, by omitting an expensive sub-view, use a binding to make that view's IsVisible initially be "false". This will keep it out of the visual tree, avoiding most of the cost of building it. Place the (invisible) view in a grid cell, whose dimensions are constant (either in DPs or "*" - anything other than "Auto".) So that layout will be "ready" for that view, when you make it visible.
APPROACH 1:
Now you just need a binding in view model that will change IsVisible to "true".
The simplest hack is to, in OnAppearing, fire an action that will change that variable after 250 ms.
APPROACH 2:
The clean alternative is to create a custom page renderer, and override "draw".
Have draw, after calling base.draw, check an action property on your page.
If not null, invoke that action, then clear it (so only happens once).
I do this by inheriting from a custom page base class:
XAML for each of my pages (change "ContentPage" to "exodus:ExBasePage"):
<exodus:ExBasePage
xmlns:exodus="clr-namespace:Exodus;assembly=Exodus"
x:Class="YourNamespace.YourPage">
...
</exodus:ExBasePage>
xaml.cs:
using Exodus;
// After creating page, change "ContentPage" to "ExBasePage".
public partial class YourPage : ExBasePage
{
...
my custom ContentPage. NOTE: Includes code not needed for this, related to iOS Safe Area and Android hardward back button:
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
namespace Exodus
{
public abstract partial class ExBasePage : ContentPage
{
public ExBasePage()
{
// Each sub-class calls InitializeComponent(); not needed here.
ExBasePage.SetupForLightStatusBar( this );
}
// Avoids overlapping iOS status bar at top, and sets a dark background color.
public static void SetupForLightStatusBar( ContentPage page )
{
page.On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea( true );
// iOS NOTE: Each ContentPage must set its BackgroundColor to black or other dark color (when using LightContent for status bar).
//page.BackgroundColor = Color.Black;
page.BackgroundColor = Color.FromRgb( 0.3, 0.3, 0.3 );
}
// Per-platform ExBasePageRenderer uses these.
public System.Action NextDrawAction;
/// <summary>
/// Override to do something else (or to do nothing, i.e. suppress back button).
/// </summary>
public virtual void OnHardwareBackButton()
{
// Normal content page; do normal back button behavior.
global::Exodus.Services.NavigatePopAsync();
}
}
}
renderer in Android project:
using System;
using Android.Content;
using Android.Views;
using Android.Graphics;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Exodus;
using Exodus.Android;
[assembly: ExportRenderer( typeof( ExBasePage ), typeof( ExBasePageRenderer ) )]
namespace Exodus.Android
{
public class ExBasePageRenderer : PageRenderer
{
public ExBasePageRenderer( Context context ) : base( context )
{
}
protected override void OnElementChanged( ElementChangedEventArgs<Page> e )
{
base.OnElementChanged( e );
var page = Element as ExBasePage;
if (page != null)
page.firstDraw = true;
}
public override void Draw( Canvas canvas )
{
try
{
base.Draw( canvas );
var page = Element as ExBasePage;
if (page?.NextDrawAction != null)
{
page.NextDrawAction();
page.NextDrawAction = null;
}
}
catch (Exception ex)
{
// TBD: Got Disposed exception on Android Bitmap, after rotating phone (in simulator).
// TODO: Log exception.
Console.WriteLine( "ExBasePageRenderer.Draw exception: " + ex.ToString() );
}
}
}
}
To do some action after the first time the page is drawn:
public partial class YourPage : ExBasePage
{
protected override void OnAppearing()
{
// TODO: OnPlatform code - I don't have it handy.
// On iOS, we call immediately "DeferredOnAppearing();"
// On Android, we set this field, and it is done in custom renderer.
NextDrawAction = DeferredOnAppearing;
}
void DeferredOnAppearing()
{
// Whatever you want to happen after page is drawn first time:
// ((MyViewModel)BindingContext).ExpensiveViewVisible = true;
// Where MyViewModel contains:
// public bool ExpensiveViewVisible { get; set; }
// And your XAML contains:
// <ExpensiveView IsVisible={Binding ExpensiveViewVisible}" ... />
}
}
NOTE: I do this differently on iOS, because Xamarin Forms on iOS (incorrectly - not to spec) calls OnAppearing AFTER the page is drawn.
So I have OnPlatform logic. On iOS, OnAppearing immediately calls DeferredOnAppearing. On Android, the line shown is done.
Hopefully iOS will eventually be fixed to call OnAppearing BEFORE,
for consistency between the two platforms.
If so, I would then add a similar renderer for iOS.
(The current iOS implementation means there is no way to update a view before it appears a SECOND time, due to popping the nav stack.
instead, it appears with outdated content, THEN you get a chance
to correct it. This is not good.)

Windows 10 - programming Cortana

I am trying to programm a litte application for Cortana.
My idea is, that i say: (I enabled the "Hey Cortana" feature)
Hey Cortana, Convert 45 degrees to farenheit
and I get (in the moment) a log in my Output window (Visual Studio). I tried to say exact this sentence and Cortana understood me perfectly, but Cortana opened the browser and entered it into Bing.
Why? What did I do wrong? I don't get any Syntax Error.
This is my Code:
// commands.xml
<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
<CommandSet xml:lang="en-us" Name="MyCommands_en-us">
<CommandPrefix> Convert, </CommandPrefix>
<Example> Convert 45 degrees to farenheit </Example>
<Command Name ="farenheitToDegrees">
<Example> 73 farenheit to degrees</Example>
<ListenFor> {farenheit} farenheit to degrees </ListenFor>
<Feedback> {farenheit} are ... in degrees </Feedback>
<Navigate/>
</Command>
<Command Name="degreesToFarenheit">
<Example> 45 degrees to farenheit </Example>
<ListenFor> {degrees} degrees to farenheit </ListenFor>
<Feedback> {degrees} degrees are ... in fareneheit </Feedback>
<Navigate/>
</Command>
<PhraseTopic Label="degrees" Scenario="Dictation">
<Subject>Temperature</Subject>
</PhraseTopic>
<PhraseTopic Label="farenheit" Scenario="Dictation">
<Subject>Temperature</Subject>
</PhraseTopic>
</CommandSet>
</VoiceCommands>
// App.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.ApplicationModel.VoiceCommands;
using Windows.Storage;
using Windows.Media.SpeechRecognition;
namespace HelloWorld
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
Microsoft.ApplicationInsights.WindowsCollectors.Session);
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected async override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
var storageFile =
await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///commands.xml"));
await
Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(storageFile);
}
protected override void OnActivated(IActivatedEventArgs e)
{
// Was the app activated by a voice command?
if (e.Kind != Windows.ApplicationModel.Activation.ActivationKind.VoiceCommand)
{
return;
}
var commandArgs = e as Windows.ApplicationModel.Activation.VoiceCommandActivatedEventArgs;
SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;
// Get the name of the voice command and the text spoken
string voiceCommandName = speechRecognitionResult.RulePath[0];
string textSpoken = speechRecognitionResult.Text;
switch (voiceCommandName)
{
case "farenheitToDegrees":
string farenheit = speechRecognitionResult.SemanticInterpretation.Properties["farenheit"][0];
System.Diagnostics.Debug.WriteLine((Convert.ToInt32(farenheit) - 32) / 1.8);
break;
case "degreesToFarenheit":
string degrees = speechRecognitionResult.SemanticInterpretation.Properties["degrees"][0];
System.Diagnostics.Debug.WriteLine(Convert.ToInt32(degrees) * 1.8 + 32);
break;
default:
System.Diagnostics.Debug.WriteLine("None of my bussiness");
break;
}
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}
can somebody help me?
The VCD definition file you've listed above doesn't have either a PhraseTopic or PhraseList to define the parts you've got in curly braces:
<ListenFor> {farenheit} farenheit to degrees </ListenFor>
I'm guessing you probably wanted a PhraseTopic because that allows for an unconstrained dictation suitable for a wide range of numbers, something like this:
<PhraseTopic Label="farenheit" Scenario="Dictation">
<Subject>Temperature</Subject>
</PhraseTopic>
See the spec for VCD's here on msdn, you might want to play with tweaking the Scenario value. This does mean you'll need to handle the text you get as the farenheit term yourself, of course, but typically dictated text for numbers comes through in textual '1234' form (but not in 100% of cases).
check the properties of your VCD file, values shoud be: Buil Action = Content, Copy to Output Directory = Copy always. Anyway, I hope that you registered the vcd file:
VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri("ms-appx:///VCD.xml"));
Check this MVA video about Cortana: https://www.microsoftvirtualacademy.com/en-US/training-courses/universal-windows-app-development-with-cortana-and-the-speech-sdk-8487
Well... Seems that you have understood all the steps but still something is missing...
Here's an example that I have made regarding Cortana's foreground functionality:
Here's the VCD...
<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
<CommandSet xml:lang="en-us" Name="HomeControlCommandSet_en-us">
<CommandPrefix>HomeControl</CommandPrefix>
<Example>Control alarm, temperature, light and others</Example>
<Command Name="Activate_Alarm">
<Example>Activate alarm</Example>
<ListenFor>[Would] [you] [please] activate [the] alarm [please]</ListenFor>
<ListenFor RequireAppName="BeforeOrAfterPhrase">Activate alarm</ListenFor>
<ListenFor RequireAppName="ExplicitlySpecified">Activate {builtin:AppName} alarm</ListenFor>
<Feedback>Activating alarm</Feedback>
<Navigate />
</Command>
After create this definitions, you need to registry it at App Startup:
protected async override void OnLaunched(LaunchActivatedEventArgs e)
{
...
// Install the VCD
try
{
StorageFile vcdStorageFile = await Package.Current.InstalledLocation.GetFileAsync(#"HomeControlCommands.xml");
await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdStorageFile);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("There was an error registering the Voice Command Definitions", ex);
}
}
An then override App.OnActivated method to handle when the events are triggered:
protected override void OnActivated(IActivatedEventArgs e)
{
// Handle when app is launched by Cortana
if (e.Kind == ActivationKind.VoiceCommand)
{
VoiceCommandActivatedEventArgs commandArgs = e as VoiceCommandActivatedEventArgs;
SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;
string voiceCommandName = speechRecognitionResult.RulePath[0];
string textSpoken = speechRecognitionResult.Text;
IReadOnlyList<string> recognizedVoiceCommandPhrases;
System.Diagnostics.Debug.WriteLine("voiceCommandName: " + voiceCommandName);
System.Diagnostics.Debug.WriteLine("textSpoken: " + textSpoken);
switch (voiceCommandName)
{
case "Activate_Alarm":
System.Diagnostics.Debug.WriteLine("Activate_Alarm command");
break;
To see the complete tutorial, please visit this link and a working project is here. Also, if you interested in respond to the user through Cortana window, check this post regarding Cortana in background
I think you are missing a part of the command.
You're asking for Cortana to convert degrees to Fahrenheit, and the program is confused because you're not being specific enough.
If you want Cortana to covert from degrees Celsius to degrees Fahrenheit, you have to tell it specifically Celsius to Fahrenheit.

How to dismiss a Alert Dialog in Mono for android correctly?

In my application i have a Custom AlertView, which works quite good so far. I can open it the first time, do, what i want to do, and then close it. If i want to open it again, i'll get
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first
so, here some code:
public Class ReadingTab
{
...
private AlertDialog AD;
...
protected override void OnCreate(Bundle bundle)
{
btnAdd.Click += delegate
{
if (IsNewTask)
{
...
AlertDialog.Builer adb = new AlertDialog.Builer(this);
...
View view = LayoutInflater.Inflate(Resource.Layout.AlertDView15ET15TVvert, null);
adb.setView(view)
}
AD = adb.show();
}
}
}
that would be the rough look of my code.
Inside of btnAdd are two more buttons, and within one of them (btnSafe) i do AD.Dismiss() to close the Alert dialoge, adb.dispose() hasn't done anything.
the first time works fine, but when i call it the secon time, the debugger holds at AD = adb.show(); with the Exception mentioned above.
So what do i have to do, to remove the Dialoge from the parent? i can't find removeView() anywhere.
If you are setting up an AlertView once and then using it in multiple places (especially if you are using the same AlertView across different Activities) then you should consider creating a static AlertDialog class that you can then call from all over the place, passing in the current context as a parameter each time you want to show it. Then when a button is clicked you can simply dismiss the dialog and set the instance to null. Here is a basic example:
internal static class CustomAlertDialog
{
private static AlertDialog _instance;
private const string CANCEL = #"Cancel";
private const string OK = #"OK";
private static EventHandler _handler;
// Static method that creates your dialog instance with the given title, message, and context
public static void Show(string title,
string message,
Context context)
{
if (_instance != null)
{
throw new Exception(#"Cannot have more than one confirmation dialog at once.");
}
var builder = new AlertDialog.Builder(context);
builder.SetTitle(title);
builder.SetMessage(message);
// Set buttons and handle clicks
builder.SetPositiveButton(OK, delegate { /* some action here */ });
builder.SetNegativeButton(CANCEL, delegate { /* some action here */});
// Create a dialog from the builder and show it
_instance = builder.Create();
_instance.SetCancelable(false);
_instance.Show();
}
}
And from your Activity you would call your CustomAlertDialog like this:
CustomAlertDialog.Show(#"This is my title", #"This is my message", this);

Eclipse: Notification when methods are renamed? before/after

I am looking for an event or notification that enables me to react in my Eclipse-Plugin when methods of a (java)classes are changed (renamed or removed/added).
I am particularly interested in the IJavaElement representation of the method that is changed.
Does some kind of event exists that provides me with this kind of information?
this is my plugin.xml
<extension
point="org.eclipse.ltk.core.refactoring.renameParticipants">
<renameParticipant
class="bookmark.renameparticipant.JavaElementRenameParticipant"
id="bookmark-pp.bookmark.renameParticipant1"
name="name">
<enablement>
<with
variable="element">
<or>
<instanceof
value="org.eclipse.jdt.core.ICompilationUnit">
</instanceof>
<instanceof
value="org.eclipse.jdt.core.IType">
</instanceof>
<instanceof
value="org.eclipse.jdt.core.IMethod">
</instanceof>
<instanceof
value="org.eclipse.jdt.core.IField">
</instanceof></or>
</with>
</enablement>
</renameParticipant>
and my source of my rename participant:
I set a breakpoint in the init-method of the participant, but if I use CTRL+2+R in Eclipse not even the init is called:
#Override
protected boolean initialize(Object element) {
if (!(element instanceof IJavaElement)) {
return false;
}
oldHandleId = ((IJavaElement) element).getHandleIdentifier();
detectElementType((IJavaElement) element);
newHandleId = generateNewHandleId(oldHandleId);
if (!initSuccessful()) {
return false;
}
return true;
}
I think you are looking for rename participants. See the extension point org.eclipse.ltk.core.refactoring.renameParticipant.
You get a chance to hook into a refactoring and you get a callback when the refactoring starts through the checkConditions method as well as when it ends through the createChange method.

Resources