How to resume Android Activity programmatically fr

2020-01-27 05:19发布

问题:

Situation:

  1. Let's say I have currently working launched application Activity A.
  2. After some time I am pressing "Home" button. Application A goes to background.
  3. At this time, I am starting to use another app B - youtube for example or etc.
  4. Something happens (doesn't matter what in this context, let's say timer finished calculating time) in the application A which currently is minimized to background.
  5. On the event occurrence, application A activity automatically resumes from background.

Question:

How to accomplish step 5? Basically I need to know how to resume application from background programmatically.

I tried to launch intent to "restart" my application activity but it didn't worked:

Intent intent = new Intent(context, MainActivity.class);
            intent.setAction(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            context.startActivity(intent);

My manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.taxti"
    android:versionCode="43"
    android:versionName="1.5.3" >     

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="21" />

    <permission
        android:name="com.example.taxti.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <uses-permission android:name="com.example.taxti.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />       
    <permission android:name="com.taxti.permission.C2D_MESSAGE"
                android:protectionLevel="signature" />
    <uses-permission android:name="com.taxti.permission.C2D_MESSAGE" />     
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />   
    <uses-permission android:name="android.permission.CALL_PHONE" />  
    <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
    <uses-permission android:name="android.permission.CLEAR_APP_CACHE" />

    <application
        android:allowBackup="true"        
        android:icon="@drawable/ic_launcher"
        android:hardwareAccelerated="true"
        android:label="@string/app_name"
        android:name="com.taxti.Globals"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.taxti.InitialActivity"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="sensorLandscape"
            android:theme="@style/MyTheme" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.taxti.MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="sensorLandscape"
            android:theme="@style/MyTheme">
        </activity>

        <service android:name=".MainActivityForegroundService" />

        <intent-filter>
                <action android:name="android.net`enter code here`.conn.CONNECTIVITY_CHANGE" />                
        </intent-filter>

       <intent-filter>
            <action android:name="android.intent.action.CALL_PRIVILEGED" />
            <category android:name="android.intent.category.DEFAULT" />     
            <action android:name="android.intent.action.DIAL" />
            <action android:name="android.intent.action.CALL_BUTTON" />     
            <category android:name="android.intent.category.BROWSABLE" />           
            <data android:scheme="tel" />
       </intent-filter>

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="xxxx" />             
        <uses-library android:name="com.google.android.maps" />

        <receiver
            android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >   
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />               
                <category android:name="com.taxti" />
            </intent-filter>

        </receiver>

    </application>

</manifest>

回答1:

In order to bring your app to the foreground, you must call startActivity() from another context (either a Service or a BroadcastReceiver). Just calling startActivity() from within an Activity won't bring your app to the foreground.

You don't need the ACTION and CATEGORY in your Intent, but you do need to set Intent.FLAG_ACTIVITY_NEW_TASK.



回答2:

If your activities are on different tasks, you can use this to bring the activity's task to foreground:

ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); 
activityManager.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);

You would need android.permission.REORDER_TASKS in order to do so. It works even in Android M, however getting an intent from a service works better in some cases.



回答3:

Just establish a Service, doing whatever you want it to in the background. Or even better: Do something in the background, listen to it with a listener, bind a Service as soon as the event you waited for occurs (timer etc). Now that you are in the Service, you just call the Activity that should be on foreground like you would from anywhere else:

Intent i = new Intent(MyService.this, MyActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyService.this.startActivity(i);


回答4:

David Wasser answer helped to solve my problem.

My Activity is running in a foreground Service so I had to call startActivity() method from that Service context.

Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mServiceContext.startActivity(intent);


回答5:

To Resume application from background programmatically will

Make your activity FOREGROUND, User's current activity in BACKGROUND. User's work is GONE

This is not right behavior from user perspective. Additionally, if we resume activity programmatically, the activity lifecycle will be broken. The activity states will be lost.

Alternative :

You can provide NOTIFICATION when your timer, task (anything) is complete in background. If user is interested in checking your activity then he/she can check from NOTIFICATION without interrupting current work



回答6:

The best way to do it I think is via an IntentService. It works this way too, and it's probably the easiest way. So the sequence is: register a receiver in the Activity (in onCreate) to listen for the event you want, then when the receiver gets the event, it launches an IntentService the standard way and this in turn starts the Activity.
This way it will put the app in front of other apps, both active and hidden ones. (But this should be used with caution. Normally the user won't like another app popping up in front of the one he's working with, except if there's a very good reason for it.)
On my KitKat device (4.4.x), I tested it and I can bring the app to front by calling startActivity from a receiver in the Activity only if there is no other app open, that is my app is hidden under the home screen. Then it will come on top. If another app is open, even if it's also hidden (but in front of my app; I actually didn't test to see what happens if both apps are hidden and mine is in front, but that's not very important), then it won't come on top if started from within the same Activity. So to make it always pop up you need to use an IntentService (or another way but this is as far as I know the simplest one).