bring Android activity to front from background thread - android

I have an activity that starts the system browser via Intent. Short before it does that I do a HTTP GET to some other URL. This GET will be answered as soon as the user finishes his task in the browser (logging in using OAuth).
I'd like to be able to close down the browser and / or get my application's activity back to the front.
I do not want to use a WebView because I'd like to avoid the perception that I might be trying to spy on passwords.
Any idea how to solve this? Is it possible at all?
Thanks a bunch!
Daniel

Make sure OAuth opens up URL which is something like yourapp://success
Next you add a intent filter to handle this custom protocol and address. More details are at http://developer.android.com/guide/topics/intents/intents-filters.html#ifs

Here's what did the trick in my project.
The application manifest is pretty standard:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Here's a code snippet of the background thread that sends the intent to re-show the activity:
public class AlarmThread extends Thread {
private int mSleepTime;
public AlarmThread(int sleepSeconds) {
super("AlarmThread");
mSleepTime = sleepSeconds * 1000;
}
#Override
public void run() {
Log.i("thread", "started sleeping for " + mSleepTime + " milliseconds");
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException e) {
// ignored
}
Log.i("thread", "creating intent to bring activity to foreground");
Intent intent = new Intent(MainActivity.getContext(), MainActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainActivity.getContext().getApplicationContext().startActivity(intent);
}
}
Note that the trick is in the MainActivity.getContext().getApplicationContext().startActivity(intent); part (last line above).
In the MainActivity, I added the getContext method:
public static Context getContext() {
return mInstance;
}
And the member 'mInstance' is set in the 'onCreate':
private static MainActivity mInstance = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Other code....
mInstance = this;
}

Related

Android Intent: How to get data back from a browser switch

I'm currently trying to implement mollie payment into the flutter framework. For that I want to build a plugin in Java. So mollie has a very good documentation how to implement their API into an android app with Java. So the problem is when I hit the payment button in my app the browser opens with the correct checkout page. After the customer select his preferred payment method mollie goes back to my app, but I always get a empty query...
So this is my code for the flutter plugin
public class MolliePlugin implements MethodCallHandler, PluginRegistry.ActivityResultListener {
Activity activity;
Result activeResult;
Context context;
Intent intent;
boolean getData;
private static final int REQUEST_CODE = 0x1337;
MolliePlugin(Registrar registrar){
activity = registrar.activity();
}
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "mollie");
channel.setMethodCallHandler(new MolliePlugin(registrar));
}
#Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("startPayment")) {
activeResult = result;
String checkout = call.argument("checkoutUrl");
startPayment(checkout);
}
else {
result.notImplemented();
}
}
/// Start the browser switch with a ACTION_VIEW
void startPayment(String checkoutUrl) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW,Uri.parse(checkoutUrl));
activity.startActivity(browserIntent);
}
So in the docs of mollie is written that I have to put the following code into the onCreate() function in my MainActivity:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//...
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
String paymentId = uri.getQueryParameter("id");
// Optional: Do stuff with the payment ID
}
}
So when I put this into the onCreate() in my MainActivity of my Flutter app I get always an ACTION_RUN back after I was routed back to my app. So I used the onNewIntent() function which gives me the correct action after coming back to my app (any ideas why?):
public class MainActivity extends FlutterActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d("Action is: ",intent.getAction());
String paymentId = "No Id";
if (Intent.ACTION_VIEW.equals(intent.getAction()) && intent != null) {
Uri uri = intent.getData();
// This has no data...
Log.d("query ",intent.getDataString());
paymentId = uri.getQueryParameter("id");
// Optional: Do stuff with the payment ID
}
}
}
So here I get an empty query. the intent.getData() only returns my returnUrl which I have to set up in my AndroidManifest (see below). The returnUrl works fine but it has no data included after checking out and swichting back to the app...
My AndroidManifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plugon.mollie_example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="mollie_example"
android:icon="#mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in #style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<data
android:host="payment-return"
android:scheme="molli" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
</application>
</manifest>
Any ideas what I'm doing wrong?

Splash screen at the beginning of app

I need some help. I have a problem with my app. I want to put a splash screen at the beginning. I have done it before. I have made the code, the layout, and all works perfectly in a new project! When I put the code I run it on my phone and the layout in my application, the application runs perfectly without any errors. But when I open it on my phone, it stops and it doesn't open it!!! Can you suggest something??
my android manifest.xml:
android:name=".activities.SplashScreenActivity"
android:label="#string/splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Assuming you want to launch Main activity from your SplashScreenActivity.
In your SplashScreenActivity's onCreate():
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
finish();
The first 2 lines launch Main activity through an Intent, and the 3rd line kills SplashScreenActivity so you cannot go back to it from MainActivity.
public class SplashScreenActivity extends AppCompatActivity {
private int SLEEP_TIMER = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_splash_screen);
View imageView = findViewById(R.id.imageView);
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade);
imageView.startAnimation(animation);
getSupportActionBar().hide();
LogoLauncher logoLauncher = new LogoLauncher();
logoLauncher.start();
}
private class LogoLauncher extends Thread {
public void run() {
try {
sleep(1000 * SLEEP_TIMER);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent intent = new Intent(SplashScreenActivity.this,LoginActivity.class);
startActivity(intent);
SplashScreenActivity.this.finish();
}
}

Ereza CustomActivityOnCrash startActivity with Intent

I've been trying to implement an custom UncaughtExceptionHandler into my application and I've discovered the library Ereza/CustomActivityOnCrash.
I have added all the code as described in the README (https://github.com/Ereza/CustomActivityOnCrash) but I still can't seem to get it to work. When I force my app to crash, a white screen pops up and then immediately disappears.
Any ideas what might be causing this? below is some of my code
AndroidManifest
<activity
android:name="com.test.SplashActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.test.MainActivity"
android:label="MainActivity"
android:screenOrientation="portrait"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="cat.ereza.customactivityoncrash.RESTART" />
</intent-filter>
</activity>
<activity
android:name="com.test.ErrorActivity"
android:label="Error"
android:screenOrientation="portrait"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="cat.ereza.customactivityoncrash.ERROR" />
</intent-filter>
</activity>
Application class
public class TestApplication extends Application {
private static TestApplication mInstance;
private TimeZone usersDefaultTimeZone;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
//Customization for CustomActivityOnCrash
//Show (TRUE) or Hide (FALSE) the stack trace on the error activity
CustomActivityOnCrash.setShowErrorDetails(false);
//Enable Restart (TRUE) 'Restart App' button
//Disable Restart (FALSE) 'Close App' button
CustomActivityOnCrash.setEnableAppRestart(true);
//This sets a custom error activity class instead of the default one.
CustomActivityOnCrash.setErrorActivityClass(ErrorActivity.class);
//This sets a EventListener to be notified of events regarding the error activity,
//CustomActivityOnCrash.setEventListener(new CustomEventListener());
//Specify the Activity to to restart the application
CustomActivityOnCrash.setRestartActivityClass(MainActivity.class);
//Install CustomActivityOnCrash
CustomActivityOnCrash.install(this);
//Now initialize your error handlers as normal
Fabric.with(this, new Crashlytics());
}
public static synchronized TestApplication getInstance() {
return mInstance;
}
static class CustomEventListener implements CustomActivityOnCrash.EventListener{
#Override
public void onLaunchErrorActivity() {
Log.i("BookingApp", "onLaunchErrorActivity()");
Crashlytics.logException(new Exception("Unknown Exception Caught & Error screen displayed to user"));
}
#Override
public void onRestartAppFromErrorActivity() {
Log.i("BookingApp", "onRestartAppFromErrorActivity()");
Answers.getInstance().logCustom(new CustomEvent("Restart After Crash"));
}
#Override
public void onCloseAppFromErrorActivity() {
Log.i("BookingApp", "onCloseAppFromErrorActivity()");
Answers.getInstance().logCustom(new CustomEvent("Close After Crash"));
}
}
}
Hi put following code in Application class and modify as you want for handeling unhandled exceptions:
#Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e);
}
});
}
public void handleUncaughtException(Thread thread, Throwable e) {
e.printStackTrace(); // not all Android versions will print the stack trace automatically
//Work what you want to do....
//start new activity with clearing task
Intent intent = new Intent(this, ActivityClass.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
//end
System.exit(2); // kill off the crashed app
}
Hope this help, I am using in my app... works.
After some more investigation I discovered that this library/code doesn't like being run in debug mode. If I installed the application on my device and launched it from there (rather than using Debug from Android Studio), it seemed to work fine.
This is most likely caused by the ErrorActivity not being specified as part of another process.
From the library documentation, regarding the usage of a custom error activity:
If you use this, the activity must be declared in your AndroidManifest.xml, with process set to :error_activity.

How to put the a picture before the app starts?

I'm trying to put a picture in my app but not really sure how.
Do I need a new activity for it? If so, how that activity will understand when to stop and go to the real program?
To clarify what I'm trying to do: When you open any app probably I think that they will have what I'm talking about. For example, the Youtube app when opened there will be a screen showing a the logo of Youtube before it opens the real app. I think this screen takes about 3 to 5 seconds.
Use splash activity as it was sais below. Here's example:
public class SplashActivity extends Activity {
private static String TAG = SplashActivity.class.getName();
private static long SLEEP_TIME = 2; // Time in seconds to show the picture
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE); // Removes title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Removes notification bar
setContentView(R.layout.splash_screen); //your layout with the picture
// Start timer and launch main activity
IntentLauncher launcher = new IntentLauncher();
launcher.start();
}
private class IntentLauncher extends Thread {
#Override
/**
* Sleep for some time and than start new activity.
*/
public void run() {
try {
// Sleeping
Thread.sleep(SLEEP_TIME*1000);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
// Start main activity
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
SplashActivity.this.startActivity(intent);
SplashActivity.this.finish();
}
}}
And don't forget to add to the manifest
<activity
android:name=".SplashActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
It called Splash Screen
You should to create new activity which has a timer. After 1-2 seconds it launches your main activity.
How to implement Splash Screen in android

Starting the Main activity from another activity

I am trying to achieve following case on Android, but no success:
1) Launch Application (Launcher Activity which is a subclass of Base Activity). The Base Activity has code as follows:
///This is in BaseActivity
#Override
public void onCreate(Bundle instance)
{
super.onCreate(instance);
//Config.isLoggedIn() is a static function.
if(! Config.isLoggedIn())
{
////Config.startLoginActivity is a static function
Config.startLoginActivity(this, getIntent());
finish();
}
}
The Config.startLoginActivity functions is defined as
public static void startLoginActivity(final Context ctx, final Intent finishIntent)
{
Intent i = new Intent(ctx, ItemListActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("FINISH_INTENT", finishIntent);
ctx.startActivity(i);
}
Now, the ItemListActivity contains a list of Items as {Item1, Item2, Item3}. In ItemListActivity, I am saving the passed "finishIntent" as
///This is ItemListActivity onCreate Method
if(getIntent().hasExtra("FINISH_INTENT"))
mFinishIntent = getIntent().getParcelableExtra("FINISH_INTENT");
and the onItemListSelected method is described as follows :
#Override
public void onItemSelected(String id) {
Config.setLogInState(true);
if(mFinishIntent != null)
{
Log.i("ITEMLISTACTIVITY", "Class Name = " + mFinishIntent.getClass().getName());
Log.i("ITEMLISTACTIVITY", "Starting mFinishIntent Activity");
startActivity(mFinishIntent);
finish();
}
}
But the issue is the Main Activity is not being launched again, Android takes me to the home screen instead. While looking for a solution, I saw that Google I/O app has the same implementation and that works flawlessly but in my case it is not. I am unable to figure it out. Please help.
Thanks in Advance.
Manifest File is as follows :
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.app.myapplication.ItemListActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.app.myapplication.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Ok Here is a quick help which works for 100 percent which I'm using not mostly but EVERYTIME! you must past it through intent and in your case here it is how it must look like.
Intent intent = new intent(//name of your activity in which you are at the moment.this, //name of activity to which you want to go.class);
startActivity(intent);
Hope this will help

Categories

Resources