How to show the "Send feedback to X" dialog? [duplicate] - android

This question already has answers here:
How to launch the Google Play intent in 'Give Feedback' mode on Android?
(3 answers)
Closed 8 years ago.
Background
Some of Google's apps allow you to send feedback from within the app, instead of going to the play store.
For example this one (of this app) :
compare this to the original one:
The question
Is it possible to open this dialog?
If so, how? And what really happens when the user posts the feedback? Is it being sent directly to the developer console? Can the developer return an answer to such a feedback? Can the dialog request that the user would leave an email? What are the features of this dialog?
If not, what do they use? It looks really similar to the dialog of sending information about crashes. Could it be that they use the same mechanism?
The reason why i'm thinking it's the same mechanism of sending errors is this post i've written, but it's supported only from API 14 , and i'm not sure about the consequences...

Yes this is the crash report dialog. Yes the report goes to the developer console. No you cannot reply to the feedback. Yes, per the post you referenced it requires API 14 and can't be used otherwise. The dialog cannot be customized. The best way to see the features of the dialog is to open it using an app that provides it.
Based on your questions, it sounds that your requirements exceed what this dialog is capable of and you may need to invent a home-grown solution or use a third-party solution.
I've used this code fragment to enable sending feedback and explicitly opening the dialog with handled exceptions.
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public ApplicationErrorReport createErrorReport (Exception e) {
ApplicationErrorReport report = new ApplicationErrorReport ();
report.packageName = report.processName = this.getPackageName ();
report.time = System.currentTimeMillis ();
report.type = null == e ? ApplicationErrorReport.TYPE_NONE : ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
if (null != e) {
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo ();
crash.exceptionClassName = e.getClass ().getSimpleName ();
crash.exceptionMessage = e.getMessage ();
StringWriter writer = new StringWriter ();
PrintWriter printer = new PrintWriter (writer);
e.printStackTrace (printer);
crash.stackTrace = writer.toString ();
StackTraceElement stack = e.getStackTrace ()[0];
crash.throwClassName = stack.getClassName ();
crash.throwFileName = stack.getFileName ();
crash.throwLineNumber = stack.getLineNumber ();
crash.throwMethodName = stack.getMethodName ();
report.crashInfo = crash;
}
return report;
}

Related

How to programmatically connect to wifi in Android

I've been searching on this for quite some time, and have found lots of solutions that ultimately use the Android GUI to prompt the end-user for connection/confirmation. We would like to present a user with a form and directly connect to the specified network. I understand from a security perspective why this is necessary, but in our case, it is a system app going on a fully managed Android device. It is not intended for general use in the Play store. We are using Xamarin, but I can adapt any Java/Kotlin code.
The closest I've found thus far is the following (using C#):
public void ConnectToWifi(string ssid, string password = "") {
var wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder().SetSsid(ssid);
if (!string.IsNullOrEmpty(password))
wifiNetworkSpecifier.SetWpa2Passphrase(password);
var networkRequest = new NetworkRequest.Builder().AddTransportType(TransportType.Wifi)?
.SetNetworkSpecifier(wifiNetworkSpecifier.Build())?.Build();
if (networkRequest is null)
return;
var theNetworkCallback = new TheNetworkCallback();
var connectivityManager = (ConnectivityManager?)MainActivity.Current.ApplicationContext?
.GetSystemService(Context.ConnectivityService);
connectivityManager?.RequestNetwork(networkRequest, theNetworkCallback);
}
It sorta works, but does prompt the end-user, and my understanding, this approach is deprecated and doesn't work well in newer versions of Android. We're hoping for a solution that works in Android 11.
I'm even fine if there's a solution to write directly to wifi files on the OS. I've seen various solutions to manually populate entries via ADB, but I'm having a tough time adapting that to Xamarin/Java (can't seem to access the /data/misc/wifi directories). Again, this is intended for use exclusively on our own managed devices.
I have a blog post about this topic here: https://blog.ostebaronen.dk/2020/11/android-11-wifi.html
Android Network API is not the greatest thing to work with as there are pitfals depending on the API level the code runs on.
From Android 10 and up a lot of the Network stuff has been restricted for "privacy" reasons, so you cannot work around not asking the user for input, unless the device is rooted or your App is set up as Device Admin.
For Android 11, there is a new API to present a system dialog and allow the user to save and connect to a network. This will look something like:
You can launch this through an Intent called android.settings.WIFI_ADD_NETWORKS:
var intent = new Intent(
"android.settings.WIFI_ADD_NETWORKS");
var bundle = new Bundle();
bundle.PutParcelableArrayList(
"android.provider.extra.WIFI_NETWORK_LIST",
new List<IParcelable>
{
new WifiNetworkSuggestion.Builder()
.SetSsid(ssid)
.SetWpa2Passphrase(password)
.Build()
});
intent.PutExtras(bundle);
StartActivityForResult(intent, AddWifiSettingsRequestCode);
You can then get the result in your Activity overriding OnActivityResult and fetching the result like so:
if (requestCode == AddWifiSettingsRequestCode)
{
if (data != null && data.HasExtra(
"android.provider.extra.WIFI_NETWORK_RESULT_LIST"))
{
var extras =
data.GetIntegerArrayListExtra(
"android.provider.extra.WIFI_NETWORK_RESULT_LIST")
?.Select(i => i.IntValue()).ToArray() ?? new int[0];
if (extras.Length > 0)
{
var ok = extras
.Select(GetResultFromCode)
.All(r => r == Result.Ok);
// if ok is true, BINGO!
return;
}
}
}
I have a repository here with the full sample: https://github.com/Cheesebaron/Android11WiFi
From using this in the wild, I've found that this API does not work nicely with some OEMs such as OnePlus and Huawei. Some of these either restrict or the System Settings App simply crashes due to a misconfiguration on their part. For those I fall back to the API's introduced in Android 10.

Xamarin Forms: Android CustomTabs close when app is backgrounded

TL;DR: CustomTabs close when app is backgrounded, but we need it to stay active. How can we achieve this?
We have an app which uses CustomTabs to login the user. We have added two-factor authentication, but this introduces a problem. When you tap the login button the custom tabs intent is launched as this:
var tcs = new TaskCompletionSource<BrowserResult>();
try
{
var activity = (Activity)Forms.Context;
var builder = new CustomTabsIntent.Builder().EnableUrlBarHiding();
var customTabsIntent = builder.Build();
customTabsIntent.Intent.AddFlags(ActivityFlags.NoHistory);
Action<string> callback = null;
callback = url =>
{
MainActivity.Callbacks -= callback;
tcs.SetResult(new BrowserResult
{
ResultType = BrowserResultType.Success,
Response = url
});
};
MainActivity.Callbacks += callback;
customTabsIntent.LaunchUrl(activity, Android.Net.Uri.Parse(options.StartUrl));
}
catch (Exception ex)
{
throw new Exception($"error: {ex.Message}");
}
return tcs.Task;
This works as expected and you can login, of course now the code for two-factor authentication code is asked, which in most cases means you have to background the app, open your authenticator (authy, Google authenticator etc.) and then come back to the app with the code. The problem is that when we re-open the app the CustomTabs and it's session is completely gone. This means you have to click it again, login again and the same happens all over. I have searched for a solution for days now. Can anyone help us finding a way to keep the CustomTabs and it's session open, so you can just fill in your authenticator code and login happily ever after?
Okay it seems to be that the following code that someone added was the one causing this:
customTabsIntent.Intent.AddFlags(ActivityFlags.NoHistory);
I removed it and it seems to work now. I see some other issues going on, but I don't think this has to do with this issue. If it does I will let you know here.

How to open Android Outlook application from an external one

I'm currently developing an Android application in order to display home screen widgets. Those ones are related to Microsoft Outlook (Events + Messages) in order to show incoming events and unread new messages in a kind of dynamic tiles.
The Msal graph library helps me a lot to authenticate and retrieve in formations which contains an identifier for each event / message results
But now I want to know if the outlook application is installed on the user device and if there is a way to open Outlook when the user click on the widget. Moreover if the user can open the corresponding clicked event or message with the identifier.
For example the Event widget currently displaying a birthday event. The user click on it. Then it opens Outlook and display directly that birthday event.
Regards
I don't think this is officially documented somewhere. But here's what you can do to find out about it.
You can list all Microsoft applications installed on your device...
val packages = context.packageManager
.getInstalledApplications(PackageManager.GET_META_DATA)
for (info in packages) {
if(info.packageName.startsWith("com.microsoft", true)){
Log.d("package name:" + info.packageName)
Log.d("Launch Activity: " + context.packageManager.getLaunchIntentForPackage(info.packageName))
}
}
Take a note of the "launch intent" displayed in the LogCat. You can use that to launch Outlook. Just make sure you don't hard-code those values because Microsoft can change those values at any point, for example the activity class can change. So, instead of doing this...
context.startActivity(
Intent().apply {
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
setPackage("com.microsoft.office.outlook")
component = ComponentName("com.microsoft.office.outlook", "com.microsoft.office.outlook.MainActivity")
}
)
Do this...
context.startActivity(
Intent().apply {
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
component = ComponentName(
outlookLaunchIntent?.component?.packageName,
outlookLaunchIntent?.component?.className
)
setPackage(outlookLaunchIntent.package)
}
)
Also, remember that getLaunchIntentForPackage and component can return null, so make sure you check for null values properly
I am relaying a suggestion from a couple of internal folks:
Please try to open the event using one of the following URLs:
ms-outlook://events/open?restid=%s&account=test#om.com (if you have a regular REST id)
ms-outlook://events/open?immutableid=%s&account=test#om.com (if you are using an immutable id)
Since immutable IDs are still in preview stage in Microsoft Graph, and customers should not use preview APIs in their production apps, I think option #1 applies to your case.
Please reply here if the URL works, or not, and if you have other related questions. I requested the couple of folks to keep an eye on this thread as well.
Well, i managed to open the outlook android application with the help of your code #Leo. As im not developping with Kotlin, ill post the JAVA code below :
Intent outlookLaunchIntent = context.getPackageManager().getLaunchIntentForPackage("com.microsoft.office.outlook");
if (outlookLaunchIntent != null) {
context.startActivity(outlookLaunchIntent );
}
Below code to open event/message in a web browser provided by webLink property of the graph API. (I only test for event and the url provided not working. Ill post a new issue on StackOverFlow for that but you already see the issue over there : https://github.com/microsoftgraph/microsoft-graph-docs/issues/4203
try {
Intent webIntent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(calendarWebLink));
webIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(webIntent);
} catch (RuntimeException e) {
// The url is invalid, maybe missing http://
e.printStackTrace();
}
However im still stuck on the decicive goal of my widget item click which is to open the relative event/email in the Microsoft Outlook Android application.
Microsoft Outlook Android app contains widgets which can achieve what im looking for. So i wonder if it is possible to list its broadcast receivers.
The best thing i found is an old manifest for that app but it doesnt help me.
https://gist.github.com/RyPope/df0e61f477af4b73865cd72bdaa7d8c2
Hi may you try to open the event using one of the url:
ms-outlook://events/open?restid=%s&account=test#om.com (If the
user is having rest id)
ms-outlook://events/open?immutableid=%s&account=test#om.com (If
the user is having immutable id)

How to check if the Android default browser has been opened? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I check if an app running on Android?
I would like to know if there is a way to check if the Android default browser (browser in Android OS) has been opened. Suppose it's opened, I would like a toast to be displayed. How can I do this programmatically?
This is the code that I used in the class that extends the Service class which listens to the logs and checks if the Android default browser has been opened. If it is then it prints a log in the LogCat stating that the Android default browser has been opened.
try {
Process mLogcatProc = null;
BufferedReader reader = null;
mLogcatProc = Runtime.getRuntime().exec(new String[] { "logcat", "-d" });
reader = new BufferedReader(new InputStreamReader(mLogcatProc.getInputStream()));
String line;
final StringBuilder log = new StringBuilder();
String separator = System.getProperty("line.separator");
while ((line = reader.readLine()) != null) {
log.append(line);
log.append(separator);
}
String w = log.toString();
Log.d("LogService", "The log is: " + w);
if (w.contains("Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.android.browser/.BrowserActivity }")) {
Log.d("LogService", "The browser has been opened");
}
}
catch (Exception e) {
Log.d("LogService", "The stacktrace is: " + e.getMessage());
}
google said on the google IO that such a behavior is considered as malware .
however , up until API 15 (including) , you can use a service that listens to the logs , and check if the desired app has started . that's because each time you run an app , android writes to the log about it .
this is considered as a workaround but a lot of apps use it and it works fine .
not sure if on the new version (API 16) reading logs would be that simple . they said that the permission to read from logs won't work anymore , and that they allow apps to read their own logs instead (without any permission needed) .
of course , if the app you are trying to monitor gives any kind of API to tell the world (via intent for example) that it has started , you can use it . i don't think that the built in web browser does that , though.

Android - how to send crash reports?

It seems that as of Android 2.2, there is a new feature for sending crash reports, as mentioned in the links:
http://www.androidcentral.com/new-android-app-crash-report-tool-already-and-running
http://android-developers.blogspot.com/2010/05/google-feedback-for-android.html
http://developer.android.com/sdk/android-2.2-highlights.html
http://www.youtube.com/watch?v=o8unC9bA4O8
How do I use this feature? Is it automatic for each application downloaded from the market (aka Google Play Store)?
Where can I find more info about this feature?
Also, is it possible to customize what is being sent, perhaps by using DefaultExceptionHandler, and put our own description of the crash?
NOTE: i know that there are plenty of tools for sending crash reports (like ACRA) , but i wish to check first if it's possible to use what's already given.
EDIT: I've succeeded modifying the exception that is passed further, hoping that this will also change the report that is sent to the developer website of Google.
Here's a sample code that is relevant for this:
private static class DefaultExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler
...
#Override
public void uncaughtException(Thread t, Throwable e)
{
final StackTraceElement[] exceptionStackTrace = e.getStackTrace();
Exception exception = new Exception("my new exception!", e);
final StackTraceElement[] newExceptionStackTrace = new StackTraceElement[exceptionStackTrace.length + 1];
System.arraycopy(exceptionStackTrace, 0, newExceptionStackTrace, 1, exceptionStackTrace.length);
newExceptionStackTrace[0] = new StackTraceElement("TEST CLASS", "TEST METHOD", "TEST FILE", 0);
exception.setStackTrace(newExceptionStackTrace);
_defaultUEH.uncaughtException(t, exception); //this will hopefully call the default handling of the exception for reporting
}
What you have described sounds like the build in feature, and as far as I know, you cannot customize this. The data will be send to the googlePlay dev account which uploaded the app. I have seen customizations made by Sense, or Custom Roms. The only way to get your own Logs, is to use the DefaultErrorHandler you mentioned. As a good practice I would check, if you can catch the error yourself, (maybe log it somewhere). If not I would rethrow this error, to give the user a chance to give you hints , what he has done

Categories

Resources