How I parsed someone else’s code. What’s useful can be found inside well-known Android applications

25.06.2017

In this article I will tell you how I analyzed the code of other people’s programs and found one interesting undocumented function for working with widgets of applications.

Widget with setting when adding

Many of us have seen the settings screen that appears when you add a widget to the device screen. For example, a weather widget might ask: “And for which city to show the forecast?” Thus, you can very flexibly configure several widgets of the same application to display different information.

To save labor on routine operations, Android Studio can for us in a couple of clicks create a workpiece with a custom widget. We only need to put the necessary checkboxes in a very informative wizard. It starts like this: New-Widget-AppWidget.

As a result of his work, two new classes will appear in the project that will automatically be written into the manifest:

<receiver android:name=".NewAppWidget">
  <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
  </intent-filter>

  <meta-data
    android:name="android.appwidget.provider"
    android:resource="@xml/new_app_widget_info"/>
</receiver>

<activity android:name=".NewAppWidgetConfigureActivity">
  <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
  </intent-filter>
</activity>

The first class is responsible for the widget itself, and the second is the activity to configure it, which is launched just when it is added. We can run this activity at different times, but it will not be very clear what kind of widget is being set up. So the moment is the most successful and it is better not to use any more places for this setting. This example of creating a widget is described in all lessons and docks. The code is simple, and you’ll figure it out yourself. I was also interested in the choice of the application icon, implemented through the widget.

Useful and useless widgets

At first I wanted to just draw the application icon in the widget. This is justified by the fact that to add an icon to the desktop, you need to add a new permission to the manifest.

<uses-permission
  android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />

And since users do not like a lot of permissions from the application, and in addition to changing the permissions in the manifest, the auto-update mechanism is turned off, I tried to make icons through the widget mechanism. And no matter how I practiced in design, I could not get an icon in one as the original one. The fault was the lack of understanding of the system. The widget is not intended to duplicate the functionality of the icon, it can be as similar to it as possible, but they are drawn in different ways, and on each patch their launcher draws a desktop with shortcuts and widgets, as his developer likes.

Having looked at someone else’s work, I was initially discouraged: at the given application the widget does not have the setup screen and just duplicates the functionality of the icon, just launching the application. At first glance, it is completely useless … But when I contacted the authors of this application, I was told that the widget shows the number of unread messages. This function is in iOS.

True, it is not entirely clear why a tiny widget was made the opportunity to change its size? Or why did not you configure the mailbox selection when adding a widget, for example?

Make icons like farproc

Once you can not make a new icon through a normal widget, you need to see how other developers do. This can help different tools, I usually use the online decompiler or decompileandroid.com. Looking at the Wifi Analyzer application manifest, I did not find the usual widget descriptions, as in the example above. But there was a widget! And he somehow ran the screen with a choice of icons!

By the method of deep searching and scientific poke it was established that an undocumented function is used here. And in the manifesto, you only need to add a new activity with a special filter:

<activity
  android:name="com.farproc.wifi.analyzer.CreateShortcutScreen"
  android:excludeFromRecents="true"
  android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
  android:noHistory="true">
  <intent-filter>
    <action android:name="android.intent.action.CREATE_SHORTCUT"/>
  </intent-filter>
</activity>

The necessary screen we launched, and then there is complete freedom of creativity. Here, for example, a completely understandable, “assembled” code for adding an icon:

private Intent m1641a(int i) {
  Intent intent = new Intent();
  Parcelable intent2 = new Intent(this, MainScreen.class);
  intent.putExtra("android.intent.extra.shortcut.ICON_RESOURCE", ShortcutIconResource.fromContext(this, f1149c[i]));
  intent.putExtra("android.intent.extra.shortcut.INTENT", intent2);
  intent.putExtra("android.intent.extra.shortcut.NAME", getString(R.string.app_name));
  return intent;
}

All the real names of methods are changed, but you can not get away from constants. They tell us the essence of what is happening.

How do I enable mobile data from a widget?

The author mentioned above has a Data Enabler Widget application. Its functionality allows you to enable and disable mobile Internet directly from the desktop through a widget without root-rights. This widget I used on the old Samsung with the version of Android 2.3, but on the last versions he does not want to work :).

In the decompiled form, the function of enabling GPRS data looks like this:

private void b(Context context)
{
  if (a != null)
  {
    break MISSING_BLOCK_LABEL_56;
  }
  a = (ConnectivityManager)context.getSystemService("connectivity");
  try
  {
    b = android/net/ConnectivityManager.getMethod("setMobileDataEnabled", new Class[] {
      Boolean.TYPE
    });
  }
  // Misplaced declaration of an exception variable
  catch (Context context) { }
  c = android/net/ConnectivityManager.getMethod("getMobileDataEnabled", new Class[0]);
  return;
  context;
}

You can find its enhanced version on Stack Overflow. In the same place, the author writes that it will work on all versions of Android, and from version 5.0 only if the application is a system one. According to my observations, so you can turn on the Internet up to version 4.3.

At the heart of this method is reflection, through it a nonpublic method is called. From a security perspective, this is a big problem, because any application can include mobiles and go online. Therefore, in recent versions of Android, this loophole was covered.

On the use of hidden methods

No matter how broad the Android platform’s capabilities, sooner or later we end up in its borders. Calling hidden methods by reflection allows us to expand these boundaries and do a little more than described in the documentation. Here, for example, the way to connect Bluetooth-enabled devices.

Most often, the boundaries of the platform are dictated by security. You can not allow an application with smartphones to connect to the Internet without the user’s knowledge or create Bluetooth-networks from devices? In this case, for convenience, you can not sacrifice safety. Therefore, in order to get a new portion of cats, the user manually connects the Internet every time. In serious projects, hidden methods will not be used, and major developers do not recommend them. In this I fully share their opinion: it is not a fact that what is working now will work tomorrow. And in the world of Android-development and without this enough headache…

Online decompilers

It can not but rejoice that with each passing day we have more and more tools for parsing applications. Here is a list of three such sites:

Нашли ошибку в тексте?

Leave a Reply

Your email address will not be published. Required fields are marked *