Robolectric getNextStartedActivity always returns launcher activity - android

I'm trying to test that calling a simple method in my Android app will start another activity. getNextStartedActivity always returns the launcher activity.
Here is the test:
#Test
public void clickingButton_shouldStartNextActivity() throws Exception {
CurrentActivity activity = Robolectric.setupActivity(CurrentActivity.class);
activity.startNextActivity();
Intent expectedIntent = new Intent(activity, NextActivity.class);
assertEquals(expectedIntent, Shadows.shadowOf(activity).getNextStartedActivity());
}
And here is the startNextActivity method in CurrentActivity:
public void startNextActivity() {
startActivity(new Intent(this, NextActivity.class));
}
When I run the test, I get LoginActivity (launcher activity) as the actual result. Here LoginActivity in AndroidManifest.xml:
<activity
android:name=".LoginActivity"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

Related

How do I specify multiple activities in AndroidManifest one for splash screen, one for mainactivity - pass the original intent to the mainactivy

I am only new to android this is my first application.
I am making progress on an app that fires when the NFC reader detects a TAG that contains NDEF messages, specifically when a URL is detect matching my domain.
I would like to add a splashscreen that fires triggered by the Android INTENT of but then passes the original INTENT to the mainactivity for further processing, I have made a start but not sure how to marry up the manifest and code to do what I am after.
MANIFEST.XML
<activity
android:name=".SplashScreenActivity"
android:theme="#style/Theme.MyApp.SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" android:theme="#style/Theme.MyApp.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"
android:host="<my custom domain>"/>
</intent-filter>
</activity>
Any help on how I should structure my Manifest to deal with this scenario, the SplashScreenActivity I could use the intent filters here to ensure that it is triggered, but then I create a new intent which means losing the NDEF extras.
public class SplashScreenActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivity(new Intent(SplashScreenActivity.this, MainActivity.class));
finish();
}
}
I would like to be able to "just pass" the whole original INTENT to the mainactivity but I am unsure how to do this.
Here is the code that extracts the NDEF messages from the INTENT any ideas appreciated.
private void readFromIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) ||
NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
logViewModel.insert(new LogEntry("READFROMINTENT ACTUALLY FIRED", "Action " + intent.getExtras()));
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
getNdefRecords(msgs);
addLinkToDbFromRecord(records);
}
//buildTagViews(msgs);
}
}
So I managed to solve this by doing the following.
I moved my intent filters from MainActivity to the .splashscreen actvity changed the category of mainactivity to DEFAULT, and allowed splashscreen activity to remain the LAUNCHER
<activity
android:name=".MainActivity"
android:theme="#style/Theme..NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.myap.app.SplashScreenActivity"
android:theme="#style/Theme.myapp.SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"
android:host="my domain"/>
</intent-filter>
</activity>
In my splashscreen activity i used the following code to copy the extras from the original intent, set the action to the expected action the mainactivity was designed to handle and used this to start the main activity
public class SplashScreenActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent startMainActivity = new Intent(SplashScreenActivity.this, MainActivity.class);
startMainActivity.putExtras(getIntent());
startMainActivity.setAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
startActivity(startMainActivity);
finish();
}
}

"onCreate()" method is not called from another intent filter

I have an Activity --> A it has two intent filters. when it is called first time the onCreate() method is called. its ok. but when it is already called by a one intent filter and then if it is called by another intent filter the onCreate() method is not called.
this is the Activity tag in manifest:
<activity
android:name=".login.Login"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTask"
>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="content"
android:mimeType="application/octet-stream"
android:pathPattern=".*\\.octopus"
tools:ignore="AppLinkUrlError" />
</intent-filter>
</activity>
This is the onCreate of the Activity:
public void onCreate(Bundle savedInstanceState) {
if (getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
super.onCreate(savedInstanceState);
// this is true when the second intent filter is used
Uri data = getIntent().getData();
if (data != null) {
getIntent().setData(null);
try {
importData(data);
} catch (Exception e) {
// warn user about bad data here
finish();
return;
}
}
......
......
}
You may want to use SingleTop mode of launchMode. By using this you will receive new Intent in onNewIntent(Intent intent) of android Activity Lifecycle method.
In other words, If the activity is already there in the top, and new Intent is starting that activity, then the new Intent will be delivered to the same Activity instance on onNewIntent() method.

Android: SingleTop behavior with multiple intent filters

I am struggling with the following strange behavior of SingleTop activities.
I have defined some intent filters in that activity:
<activity android:name="com.example.DashboardActivity"
android:screenOrientation="landscape"
android:launchMode="singleTop"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="video" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<data android:scheme="survey" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CALL" />
<data android:scheme="call" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
This code should start the activity:
webView.setWebViewClient(new WebViewClient()
{
public boolean shouldOverrideUrlLoading(WebView view, String url) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
return true;
} catch(ActivityNotFoundException e) {
Log.e(TAG,"Could not load url"+url);
}
return super.shouldOverrideUrlLoading(view, url);
}
});
in the onResume of the DashboardActivity I check for the according action:
public void onResume(){
super.onResume();
Fragment fragment = null;
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
extras.putParcelable("uri", getIntent().getData());
fragment = new VideoplayerFragment();
} else {
fragment = new DashboardFragment();
}
addOrReplaceFragment(fragment, extras);
}
But when I run this code, I always get the android.intent.action.MAIN action. If I remove the singleTop launch mode, it launches a new activity, but passes the correct intent. I have to use the same instance of the activity, so singleTop, singleTask or singleInstance must do the job. But I don't know what's going wrong here. HELP!
Intent.ACTION_VIEW.equals(intent.getAction())
Where is this intent coming from? In order to catch the new Intent you must use
onNewIntent().

Why other activity is destroying when 'Home' key is pressed.?

There are two activities ActivityA and ActivityB, both are made singleTask. Here ActivityB is of category HOME and it is set to always. I am starting ActivityA from a BroadcastReceiver on ACTION_BOOT_COMPLETED, it is starting ActivityA as expected but when HOME KEY is pressed (which is ActivityB), ActivityA is getting destroyed.
What can be the possible reason of it? How can I stop ActivityA from being destroyed? By keeping both activities singleTask.
This is the BroadcastReciever:
public class MyStartupIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED == intent.getAction()) {
Intent i = new Intent(context, ActivityA.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
}
}
}
And manifest file is as follows:
<activity
android:name="ActivityB"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="ActivityA"
android:label="#string/app_name"
android:launchMode="singleTask"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" >
</activity>

Start an Activity not from an Intent

How can I start an Activity without using an Intent? The only rule I have got is
if( var == true ) startActivity();
but startActivity(); needs an Intent as a parameter.
Just create a new intent for the activity you want to start. depending on where you are you will need the app context thought.
Intent i = new Intent(getApplicationContext(), YourActivity.class);
startActivity(i);
Here's how to navigate to a second Activity (another page) using an Intent.
public void onClick(View v)
{
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
Also, don't forget to adjust the AndroidManifest.xml for each Activity.
<application android:label="#string/app_name" android:icon="#drawable/ic_launcher">
<activity android:name="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>
<activity android:name="SecondActivity"
android:label="#string/second_label">
<intent-filter>
<action android:name="android.intent.action.SECOND" /> //should be namespace of your company I guess
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>

Categories

Resources