+
+
+ // This must run asynchronously because it involves a network request. `String` declares the parameters. `Void` does not declare progress units. `SpannableStringBuilder` contains the results.
+ private static class GetIpAddresses extends AsyncTask<String, Void, SpannableStringBuilder> {
+ // The weak references are used to determine if the activity or the alert dialog have disappeared while the AsyncTask is running.
+ private WeakReference<Activity> activityWeakReference;
+ private WeakReference<AlertDialog> alertDialogWeakReference;
+
+ GetIpAddresses(Activity activity, AlertDialog alertDialog) {
+ // Populate the weak references.
+ activityWeakReference = new WeakReference<>(activity);
+ alertDialogWeakReference = new WeakReference<>(alertDialog);
+ }
+
+ @Override
+ protected SpannableStringBuilder doInBackground(String... domainName) {
+ // Get handles for the activity and the alert dialog.
+ Activity activity = activityWeakReference.get();
+ AlertDialog alertDialog = alertDialogWeakReference.get();
+
+ // Abort if the activity or the dialog is gone.
+ if ((activity == null) || (activity.isFinishing()) || (alertDialog == null)) {
+ return new SpannableStringBuilder();
+ }
+
+ // Initialize an IP address string builder.
+ StringBuilder ipAddresses = new StringBuilder();
+
+ // Get an array with the IP addresses for the host.
+ try {
+ // Get an array with all the IP addresses for the domain.
+ InetAddress[] inetAddressesArray = InetAddress.getAllByName(domainName[0]);
+
+ // Add each IP address to the string builder.
+ for (InetAddress inetAddress : inetAddressesArray) {
+ // Check to see if this is not the first IP address.
+ if (ipAddresses.length() > 0) {
+ // Add a line break to the string builder first.
+ ipAddresses.append("\n");
+ }
+
+ // Add the IP Address to the string builder.
+ ipAddresses.append(inetAddress.getHostAddress());
+ }
+ } catch (UnknownHostException exception) {
+ // Do nothing.
+ }
+
+ // Set the label.
+ String ipAddressesLabel = activity.getString(R.string.ip_addresses) + " ";
+
+ // Create a spannable string builder.
+ SpannableStringBuilder ipAddressesStringBuilder = new SpannableStringBuilder(ipAddressesLabel + ipAddresses);
+
+ // Create a blue foreground color span.
+ ForegroundColorSpan blueColorSpan;
+
+ // Get the current theme status.
+ int currentThemeStatus = activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+
+ // Set the blue color span according to the theme. The deprecated `getColor()` must be used until the minimum API >= 23.
+ if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
+ blueColorSpan = new ForegroundColorSpan(activity.getResources().getColor(R.color.violet_500));
+ } else {
+ blueColorSpan = new ForegroundColorSpan(activity.getResources().getColor(R.color.blue_700));
+ }
+
+ // Set the string builder to display the certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
+ ipAddressesStringBuilder.setSpan(blueColorSpan, ipAddressesLabel.length(), ipAddressesStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+
+ // Return the formatted string.
+ return ipAddressesStringBuilder;
+ }
+
+ // `onPostExecute()` operates on the UI thread.
+ @Override
+ protected void onPostExecute(SpannableStringBuilder ipAddresses) {
+ // Get handles for the activity and the alert dialog.
+ Activity activity = activityWeakReference.get();
+ AlertDialog alertDialog = alertDialogWeakReference.get();
+
+ // Abort if the activity or the alert dialog is gone.
+ if ((activity == null) || (activity.isFinishing()) || (alertDialog == null)) {
+ return;
+ }
+
+ // Get a handle for the IP addresses text view.
+ TextView ipAddressesTextView = alertDialog.findViewById(R.id.ip_addresses);
+
+ // Remove the incorrect lint warning below that the view might be null.
+ assert ipAddressesTextView != null;
+
+ // Populate the IP addresses text view.
+ ipAddressesTextView.setText(ipAddresses);
+ }
+ }