/** * Alternative notifier extension with three methods not found in the standard * notifer in App Inventor, but based upon the original code. * Credits: @HalAbelson - MIT who wrote the original notifier code * Credits: @Shreyash for the Rush extension builder * * Created by: @TIMAI2 April 2021 */ package metricrat.ai2.altnotifier; import android.app.Activity; import android.app.AlertDialog; import android.widget.EditText; import android.widget.TextView; import android.widget.LinearLayout; import android.view.View; import android.content.DialogInterface; import android.view.inputmethod.InputMethodManager; import android.content.Context; import android.view.WindowManager.LayoutParams; import com.google.appinventor.components.runtime.EventDispatcher; import com.google.appinventor.components.annotations.SimpleEvent; import com.google.appinventor.components.annotations.SimpleFunction; import com.google.appinventor.components.runtime.AndroidNonvisibleComponent; import com.google.appinventor.components.runtime.ComponentContainer; import com.google.appinventor.components.runtime.errors.YailRuntimeError; import com.google.appinventor.components.runtime.util.YailList; public class AltNotifier extends AndroidNonvisibleComponent { private final Activity activity; public AltNotifier(ComponentContainer container) { super(container.$form()); activity = container.$context(); } /** ###################################################################################################### * QUESTION DIALOG */ @SimpleFunction(description = "Shows a question dialog, set by the user, and allows a" + " positive response or cancel from the user. A response event is raised ") public void ShowQuestionDialog(String question, String title, String buttonText, boolean cancelable) { QuestionAlert(question, title, buttonText, cancelable); } private void QuestionAlert(String question, String title, String buttonText, boolean cancelable) { AlertDialog.Builder alert = new AlertDialog.Builder(activity); alert.setTitle(title); alert.setMessage(question); alert.setCancelable(false); alert.setPositiveButton(buttonText, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { AfterQuestion(buttonText.toString()); } }); alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { AfterQuestion("Cancel"); } }); alert.show(); } /** * Event raised after the user has responded to ShowQuestionDialog. * @param response is the button text selected */ @SimpleEvent( description = "Event raised after the user has responded to ShowQuestionDialog.") public void AfterQuestion(String response) { EventDispatcher.dispatchEvent(this, "AfterQuestion", response); } /** ############################################################################################################## * LOGIN/PASS ENTRY DIALOG */ @SimpleFunction(description = "Shows a dialog box where the user can enter Login" + "and Password details. The user can also cancel") public void ShowLoginDialog(String message, String title, boolean cancelable) { loginInputDialog(message, title, cancelable); } private void loginInputDialog(String message, String title, boolean cancelable) { AlertDialog.Builder alert = new AlertDialog.Builder(activity); alert.setTitle(title); alert.setMessage(message); alert.setCancelable(false); LinearLayout layout = new LinearLayout(activity); layout.setOrientation(LinearLayout.VERTICAL); final EditText inputLogin = new EditText(activity); inputLogin.setHint("Login Name"); layout.addView(inputLogin); final EditText inputPass = new EditText(activity); inputPass.setHint("Password"); layout.addView(inputPass); alert.setView(layout); alert.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { HideKeyboard((View) layout); AfterLoginInput(inputLogin.getText().toString(), inputPass.getText().toString()); } }); alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { HideKeyboard((View) layout); //LoginInputCanceled(); AfterLoginInput("Cancel", "Cancel"); } }); alert.show(); // Request focus after showing dialog inputLogin.requestFocus(); // Show soft keyboard InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); } /** * Event raised after the user has responded to loginInputDialog. * @param response is the text that was entered */ @SimpleEvent(description = "Event raised after the user has responded to ShowLoginDialog.") public void AfterLoginInput(String login, String password) { EventDispatcher.dispatchEvent(this, "AfterLoginInput", login, password); } /** * Event raised when the user canceled loginInputDialog. @SimpleEvent(description = "Event raised when the user canceled ShowLoginDialog.") public void LoginInputCanceled() { EventDispatcher.dispatchEvent(this, "LoginInputCanceled"); } */ /** ############################################################################################################## * TEXT ENTRY WITH CONTENT DIALOG */ @SimpleFunction(description = "Shows a dialog box where the user can enter text, after which the " + "AfterTextInput event will be raised. If cancelable is true there will be an additional CANCEL button. " + "Entering text will raise the AfterTextInput event. The \"response\" parameter to AfterTextInput " + "will be the text that was entered, or \"Cancel\" if the CANCEL button was pressed." + "A default text (content) can be added to the text entry box") public void ShowTextDialog(String message, String title, String content, boolean cancelable) { textInputDialog(message, title, content, cancelable); } private void textInputDialog(String message, String title, String content, boolean cancelable) { AlertDialog.Builder alert = new AlertDialog.Builder(activity); alert.setTitle(title); alert.setMessage(message); alert.setCancelable(false); final EditText input = new EditText(activity); input.setText(content); alert.setView(input); alert.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { HideKeyboard((View) input); AfterTextInput(input.getText().toString()); } }); alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { HideKeyboard((View) input); //TextInputCanceled(); AfterTextInput("Cancel"); } }); alert.show(); // Request focus after showing dialog input.requestFocus(); // Show soft keyboard InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); } /** * Event raised after the user has responded to ShowTextDialog. * @param response is the text that was entered */ @SimpleEvent( description = "Event raised after the user has responded to ShowTextDialog.") public void AfterTextInput(String response) { EventDispatcher.dispatchEvent(this, "AfterTextInput", response); } /** * Event raised when the user canceled ShowTextDialog. @SimpleEvent( description = "Event raised when the user canceled ShowTextDialog.") public void TextInputCanceled() { EventDispatcher.dispatchEvent(this, "TextInputCanceled"); } */ /** ######################################################################################################### * Hide soft keyboard after user either enters text or cancels. */ public void HideKeyboard(View view) { if (view != null) { InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } }