How to use Intent.ACTION_APP_ERROR as a means for

2019-01-10 23:38发布

问题:

I would like to reuse the Intent.ACTION_BUG_REPORT in my app, as a simple means of getting user feedback.

Google Maps uses it as their "Feedback" option. But I've not been successful in firing the event.

I'm using the following in a onOptionsItemSelected(MenuItem item):

    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
    startActivity(intent);

And in my AndroidManifest.xml I've declared the following under my Activity:

    <intent-filter>
       <action android:name="android.intent.action.BUG_REPORT" />
       <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>

However, nothing seems to happen besides the screen "blink" when I select the option. The App or intent doesn't crash, it doesn't log anything. Tried it both in the Emulator and on an ICS 4.0.4 device.

I'm clealy missing something, but what?

Edit

Intent.ACTION_APP_ERROR (constant android.intent.action.BUG_REPORT) was added in API level 14, http://developer.android.com/reference/android/content/Intent.html#ACTION_APP_ERROR

回答1:

This was solved with the help from the link in @TomTasche comment above. Use built-in feedback mechanism on Android.

In my AndroidManifest.xml I added the following to the <Activity> where I want to call the Feedback agent from.

<intent-filter>
   <action android:name="android.intent.action.APP_ERROR" />
   <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

And I made a simple method called sendFeedback() (code from TomTasche blogpost)

@SuppressWarnings("unused")
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void sendFeedback() {
    try {
        int i = 3 / 0;
    } catch (Exception e) {
    ApplicationErrorReport report = new ApplicationErrorReport();
    report.packageName = report.processName = getApplication().getPackageName();
    report.time = System.currentTimeMillis();
    report.type = ApplicationErrorReport.TYPE_CRASH;
    report.systemApp = false;

    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;

    Intent intent = new Intent(Intent.ACTION_APP_ERROR);
    intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
    startActivity(intent);
    }
}

And from my SettingsActivity I call it like:

      findPreference(sFeedbackKey).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
          public final boolean onPreferenceClick(Preference paramAnonymousPreference) {
              sendFeedback();
              finish();
              return true;
          }
      });         

Verified working with Android 2.3.7 and 4.2.2.

When the sendFeedback() method is called, a "Complete action using"-dialog is opened where the user can select from three actions/icons.

The calling app, which returns to the app, and Google Play and the Feedback agent. Selecting either Google Play Storeor Send feedback will open the built-in Android feedback agent as intended.

I haven't investigated further if it's possible to skip the "Complete action using"-step, it's probably possible with the correct parameters passed to the Intent. So far, this does exactly what I wanted for now.



回答2:

Please don't mix two different intents Intent.ACTION_BUG_REPORT and Intent.ACTION_APP_ERROR. The first one is designed for old error reporting and feedback and it's supported from API v1. The second one is for sending advanced error reports (supports ApplicationErrorReport object where you can store a lot of useful informations) and was added in API v14.

For sending feedback, I am testing bellow code in my new version of APP (it also create a screenshot of the activity). This starts com.google.android.gms.feedback.FeedbackActivity, which is part of Google Play services. But question is where then I'll find the feedbacks?!

protected void sendFeedback(Activity activity) {
    activity.bindService(new Intent(Intent.ACTION_BUG_REPORT), new FeedbackServiceConnection(activity.getWindow()), BIND_AUTO_CREATE);
}

protected static class FeedbackServiceConnection implements ServiceConnection {
    private static int MAX_WIDTH = 600;
    private static int MAX_HEIGHT = 600;

    protected final Window mWindow;

    public FeedbackServiceConnection(Window window) {
        this.mWindow = window;
    }

    public void onServiceConnected(ComponentName name, IBinder service) {
        try {
            Parcel parcel = Parcel.obtain();
            Bitmap bitmap = getScreenshot();
            if (bitmap != null) {
                bitmap.writeToParcel(parcel, 0);
            }
            service.transact(IBinder.FIRST_CALL_TRANSACTION, parcel, null, 0);
            parcel.recycle();
        } catch (RemoteException e) {
            Log.e("ServiceConn", e.getMessage(), e);
        }
    }

    public void onServiceDisconnected(ComponentName name) { }

    private Bitmap getScreenshot() {
        try {
            View rootView = mWindow.getDecorView().getRootView();
            rootView.setDrawingCacheEnabled(true);
            Bitmap bitmap = rootView.getDrawingCache();
            if (bitmap != null)
            {
                double height = bitmap.getHeight();
                double width = bitmap.getWidth();
                double ratio = Math.min(MAX_WIDTH / width, MAX_HEIGHT / height);
                return Bitmap.createScaledBitmap(bitmap, (int)Math.round(width * ratio), (int)Math.round(height * ratio), true);
            }
        } catch (Exception e) {
            Log.e("Screenshoter", "Error getting current screenshot: ", e);
        }
        return null;
    }
}


回答3:

Do note that the crash report solution (as in here) is not available on pre-ICS versions of Android.

A shorter, simpler version of the solution of "kaderud" (here) :

  @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
  private void sendFeedback()
    {
    final Intent intent=new Intent(Intent.ACTION_APP_ERROR);
    final ApplicationErrorReport report=new ApplicationErrorReport();
    report.packageName=report.processName=getApplication().getPackageName();
    report.time=System.currentTimeMillis();
    report.type=ApplicationErrorReport.TYPE_NONE;
    intent.putExtra(Intent.EXTRA_BUG_REPORT,report);
    final PackageManager pm=getPackageManager();
    final List<ResolveInfo> resolveInfos=pm.queryIntentActivities(intent,0);
    if(resolveInfos!=null&&!resolveInfos.isEmpty())
      {
      for(final ResolveInfo resolveInfo : resolveInfos)
        {
        final String packageName=resolveInfo.activityInfo.packageName;
        // prefer google play app for sending the feedback:
        if("com.android.vending".equals(packageName))
          {
          // intent.setPackage(packageName);
          intent.setClassName(packageName,resolveInfo.activityInfo.name);
          break;
          }
        }
      startActivity(intent);
      }
    else
      {
      // handle the case of not being able to send feedback
      }
    }


回答4:

Starting with API level 14 you can try to use the ACTION_APP_ERROR intent but the app needs to be available on Google Play store for this to work.

Intent intent = new Intent(Intent.ACTION_APP_ERROR);
startActivity(intent);
//must be available on play store