Android shortcut implements desktop icon shortcuts to jump Android 7.1.1, similar to IOS3d touch

Keywords: Android xml Google github

Background introduction:

3D Touch is a three-dimensional touch technology, which Apple calls a new generation of multi-touch technology. It is Force Touch used on Apple Watch. The screen can sense different pressure touch. 3D Touch, the new feature of Apple's iPhone 6s, looks like a right-click on a PC. There are two new gestures, Peek Pop.

With the addition of 3d touch to IOS on the iphone 6s, many applications of fruit powder mobile phone have the function of fast access.

For example, the following figure:


3D touch needs hardware support, but Google has opened up the system and has not firmly controlled the hardware. Even if Google implemented a 3D touch, other Android vendors are not expected to update their hardware so quickly.

But there is no need for us to underestimate ourselves. Openness has the advantage of opening up and closure has the disadvantage of closure.

II. Android Realization:

Okay, don't talk too much nonsense. The theme of this article is to introduce how to implement IOS 3d touch-like functions on Android. On Android, this feature is called

Application shortcut, which shows the entrance by pressing the application icon for a long time, can also drag the shortcut to the desktop to form a separate entrance.

First, take a look at Google's introduction to shortcut:

If there is a ladder point here: Google's introduction to shortcut

Application shortcuts

If your application is located at Android 7.1 (API level 25) or higher, you can define shortcuts to specific operations in your application. These shortcuts can be displayed in the supported starter. Shortcuts allow your users to quickly start common or recommended tasks in applications.
Each shortcut refers to one or more intentions, and when the user chooses a shortcut, each intent initiates a specific action in the application. Examples of operations that you can express as shortcuts include:
  • Navigate users to specific locations in map applications
  • Sending Messages to Friends in Communication Applications
  • Play the next episode of TV programs in media applications
  • The game loads in the application to find the last save point
You can publish the following types of shortcuts for your application:
  • Static shortcuts are defined in resource files packaged into APK or application packages
  • Only at runtime can your application publish, update and delete dynamic shortcuts

If the user grants permissions, the fixed shortcut can be fixed to the supported starter at run time.

Note: Users can also create fixed shortcuts by copying the static and dynamic shortcuts of the application to the starter.

You can publish up to five shortcuts (a combination of static shortcuts and dynamic shortcuts) for your application at a time. However, some starter applications do not display all the static and dynamic shortcuts you create for your application.
There is no limit to the number of fixed shortcuts that users can create. Even if your application cannot remove fixed shortcuts, it can still disable them.

Note: Although other applications cannot access metadata in the shortcut, the starter itself can access this data. Therefore, these metadata should hide sensitive user information.

Through the introduction, we know that:

  1. There are two kinds of registration shortcuts: dynamic and static.
  2. Attention should be paid to protecting user sensitive information, such as orders and other information;
  3. It can publish, update and delete dynamically.
  4. They can be fixed to the desktop as a shortcut entry.

Static registration:

1. First create a new directory xml under res, then create a new shortcuts.xml file, path: res/xml/shortcuts.xml

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
  <shortcut
    android:shortcutId="compose"
    android:enabled="true"
    android:icon="@drawable/compose_icon"
    android:shortcutShortLabel="@string/compose_shortcut_short_label1"
    android:shortcutLongLabel="@string/compose_shortcut_long_label1"
    android:shortcutDisabledMessage="@string/compose_disabled_message1">
    <intent
      android:action="android.intent.action.VIEW"
      android:targetPackage="com.example.myapplication"
      android:targetClass="com.example.myapplication.ComposeActivity" />
    <!-- If your shortcut is associated with multiple intents, include them
         here. The last intent in the list determines what the user sees when
         they launch this shortcut. -->
    <categories android:name="android.shortcut.conversation" />
  </shortcut>
  <!-- Specify more shortcuts here. -->
</shortcuts>

2. Modify manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.william.shortcut">
  <application ... >
    <activity android:name="Main">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="android.app.shortcuts"
                 android:resource="@xml/shortcuts" />
    </activity>
  </application>
</manifest>

Note: If multiple intentions are associated with shortcuts, the system will start activities corresponding to the last intent of the shortcut in the resource file, as well as other activities in the backward stack. In this case, when the user chooses the shortcut and then presses the back button, your application will start activities corresponding to the penultimate intention of the shortcut listed in the resource file. After repeatedly pressing the Back button, this behavior pattern continues until the user clears the Backstack created by the shortcut. The next time the user presses the back button, the system navigates them back to the starter.

Dynamic registration:

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);

ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1")
    .setShortLabel("Web site")
    .setLongLabel("Open the web site")
    .setIcon(Icon.createWithResource(context, R.drawable.icon_website))
    .setIntent(new Intent(Intent.ACTION_VIEW,
                   Uri.parse("https://www.mysite.example.com/")))
    .build();

shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut));

Tracking shortcuts

To determine whether static and dynamic shortcuts should occur, the starter checks the activation history of the shortcuts. reportShortcutUsed() when any of the following events occur, you can track when a user completes a specific operation in the application by calling the method and passing in the ID of the shortcut:
Users choose a shortcut with a given ID.
The user opens the application and manually completes the operation corresponding to the same shortcut.

Disable shortcuts

Because your application and its users can fix shortcuts to the device's starter, these fixed shortcuts may lead users to perform operations that have expired or no longer exist in the application. To manage this situation, you can disable the disableShortcuts() shortcuts that you do not want users to call by calling the selected disableShortcuts() shortcuts, which deletes the specified shortcuts from the static and dynamic shortcuts list, and disables any fixed copies of these shortcuts. You can also use the overloaded version of this method to define the error messages that should be displayed when a user tries to start a disabled shortcut.

Allocate multiple intentions

When you use ShortcutInfo.Builder, you can use setIntents() instead of setIntent(). By calling setIntents(), you can start multiple activities in the application when the user chooses a shortcut, and put the last activity in the list on the backend stack. If the user then decides to press the device's back button, they will see another activity in your application instead of returning to the device's starter.

Best practices

When designing and creating shortcuts to applications, you should follow the following guidelines:

Follow shortcut design guidelines (Shortcut icon)

No ladder point here: Click Open Link

To visually align application shortcuts with the shortcuts used by system applications, follow the application shortcuts design guidelines.

Publish only four different shortcuts

Although the API currently supports up to five static and dynamic shortcuts for your application at any given time, it is recommended that you publish only four different shortcuts at any time to improve the visual appearance of the shortcuts in the starter.

Limit the length of shortcut descriptions

The space in the menu is limited and the application shortcuts can be displayed in the starter. If possible, limit the length of the "short description" of the shortcut to 10 characters and the length of the "long description" to 25 characters.

Maintain shortcuts and operating history

For each shortcut you create, consider different ways in which users can directly accomplish the same task in an application. Keep in mind that reportShortcutUsed() is invoked in each case so that the starter maintains an accurate historical record of the actions that represent your shortcut.

Update shortcuts only while retaining their meaning

When changing dynamic and fixed shortcuts, updateShortcuts() is invoked only when changing the shortcuts that retain their meaning. Otherwise, you should use one of the following methods, depending on the type of shortcut you want to recreate:
  • Dynamic shortcuts: addDynamicShortcuts() or setDynamicShortcuts().
  • Fixed shortcut: request PinShortcut ().
For example, if you create a shortcut to navigate to a supermarket, you just need to update the shortcut as long as the name of the supermarket changes but its location remains unchanged. However, if users start shopping in different supermarket locations, it's better to create new shortcuts.

Dynamic shortcuts are not retained during backup and restore

Dynamic shortcuts are not retained when devices are backed up and restored. Therefore, it is recommended that you check the number of objects returned by getDynamicShortcuts() each time the application is started and redistribute dynamic shortcuts as needed, as shown in the code snippet in the Backup and Restore section.

Now let's use our own code to achieve dynamic registration.

First, in a real business scenario, we need to determine whether the target page to jump needs to be logged in and process it separately.

So all the jump entries I specify in Demo are flash pages.

First look at Android Manifest. XML

<application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".SplashActivity"
            android:theme="@style/theme_loading">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>
        </activity>
        <activity
            android:name=".TargetActivity"
            android:screenOrientation="portrait" />
    </application>

Flash screen page code:

/**
 * Author: William Time: 2018/7/14
 * Class Description: Flash Screen Page
 */
public class SplashActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String targetAction = getIntent().getStringExtra("targetAction");
        new Handler().postDelayed(() -> {
            // In a real business scenario, you need to determine whether the target page needs to log in.
            // Here, we simply simulate a second later to jump to the target page, unified jump in MainActivity.
            Intent intent = new Intent(this, MainActivity.class);
            intent.putExtra("targetAction", targetAction);
            startActivity(intent);
            finish();// Avoid retreating to see the flash page again
        }, 1000);
    }
}

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private boolean exit;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createShortcut();
        handleShortcutEvent();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        handleShortcutEvent();
    }

    private void handleShortcutEvent() {
        String targetAction = getIntent().getStringExtra("targetAction");
        if (!TextUtils.isEmpty(targetAction)) {
            TargetActivity.startTargetPage(this, targetAction);
        }
    }

    /**
     * Dynamic Creation of Desktop Icon Length Press Menu List
     */
    public void createShortcut() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
            try {
                boolean isShortcutCreated = PreferencesUtil.readBoolean("isShortcutCreated", false);
                if (!isShortcutCreated) {// If it has been created, it will not be created again. Consider getting it from the interface.
                    ShortcutManager mShortcutManager = getSystemService(ShortcutManager.class);
                    List<ShortcutInfo> infoList = new ArrayList<>();

                    infoList.add(createShortcutInfo(ShortcutUtil.ID1, "Action-1", 0,
                            R.mipmap.ic_launcher_round, "Action-1"));
                    infoList.add(createShortcutInfo(ShortcutUtil.ID2, "Action-2", 1,
                            R.mipmap.ic_launcher_round, "Action-2"));
                    infoList.add(createShortcutInfo(ShortcutUtil.ID3, "Action-3", 2,
                            R.mipmap.ic_launcher_round, "Action-3"));
                    infoList.add(createShortcutInfo(ShortcutUtil.ID4, "Action-4", 3,
                            R.mipmap.ic_launcher_round, "Action-4"));

                    if (mShortcutManager != null)
                        mShortcutManager.setDynamicShortcuts(infoList);

                    PreferencesUtil.writeBoolean("isShortcutCreated", true);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private ShortcutInfo createShortcutInfo(String id, String label, int rank, int iconResId, String targetAction) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
            return new ShortcutInfo.Builder(this, id)
                    .setShortLabel("desktop" + label)// Set the name of the desktop icon to drag the title of the icon onto the desktop
                    .setLongLabel(label)// APP Long Press Display Title
                    .setRank(rank)// Sequential display, this is relative, it is always displayed in the nearest order from the application icon, if the icon is at the top and bottom of the desktop, the display order is opposite.
                    .setIcon(Icon.createWithResource(this, iconResId))// Shortcut icons
                    .setIntent(createIntent(targetAction))// For the purpose of jumping, setIntents() is recommended on the official website.
//                    .setIntents(new Intent[]{})
                    .build();
        }
        return null;
    }

    private Intent createIntent(String targetAction) {
        Intent intent = new Intent(this, SplashActivity.class);
        intent.setAction(Intent.ACTION_MAIN);
        intent.putExtra("targetAction", targetAction);
        return intent;
    }

    @Override
    public void onBackPressed() {
        if (!exit) {
            exit = true;
            Toast.makeText(this, "Click Exit Again", Toast.LENGTH_SHORT).show();
            getWindow().getDecorView().postDelayed(() -> {
                if (!isFinishing()) {
                    exit = false;
                }
            }, 1500);
        } else {
            Process.killProcess(Process.myPid());
            System.exit(0);
        }
    }

}

TargetActivity.java:

/**
 * Author: William Time: 2018/7/14
 * Class Description: Target Test Page
 */
public class TargetActivity extends AppCompatActivity {

    public static void startTargetPage(Context context, String targetAction) {
        Intent intent = new Intent(context, TargetActivity.class);
        intent.putExtra("targetAction", targetAction);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_target);
        String targetAction = getIntent().getStringExtra("targetAction");
        ((TextView) findViewById(R.id.tv_action)).setText(targetAction);
        String shortcutId = null;
        if (targetAction != null) {
            switch (targetAction) {
                case "Action-1":
                    shortcutId = ShortcutUtil.ID1;
                    break;
                case "Action-2":
                    shortcutId = ShortcutUtil.ID2;
                    break;
                case "Action-3":
                    shortcutId = ShortcutUtil.ID3;
                    break;
                case "Action-4":
                    shortcutId = ShortcutUtil.ID4;
                    break;
            }
            if (shortcutId != null) {
                ShortcutUtil.report(this, shortcutId);
            }
        }
    }
}

Figure 1:


Effect Figure 2:


As we set the rank order above, it is always displayed as close as possible to the application icon, as shown below:



This is where the Android application desktop shortcut jump function is basically implemented.

In fact, the best way is that the information of the icon is obtained from the interface, which makes the dynamic icon creation and update more flexible.

Of course, if the jump target page is relatively fixed, you can choose not to get from the interface, people with different opinions, wise people with different opinions!

More about Shortcut Manager API points here: Click Open Link

Demo I uploaded to github:

github point here: Click Open Link

Welcome to leave a message and discuss!!!!!


Posted by sgalatas on Wed, 02 Jan 2019 17:06:09 -0800