I'm trying to open the default calculator app in a android application. Two calculators are installed in device: default android calculator and Google Calculator.
Intent calc = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, Intent.CATEGORY_APP_CALCULATOR);
startActivity(calc);
This code is throwing an ActivityNotFoundException and shows this in logcat:
system_process W/IntentResolver: resolveIntent failed: found match, but none with CATEGORY_DEFAULT
This code have the same behavior:
Intent calc = new Intent(Intent.ACTION_MAIN);
calc.addCategory(Intent.CATEGORY_APP_CALCULATOR);
startActivity(calc);
It's a Android bug? How to open the application chooser, to let user select the default app?
Stack Trace:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] sel=act=android.intent.action.MAIN cat=[android.intent.category.APP_CALCULATOR]} }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1514)
at android.app.Activity.startActivityForResult(Activity.java:3930)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.app.Activity.startActivityForResult(Activity.java:3890)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
at android.app.Activity.startActivity(Activity.java:4213)
at android.app.Activity.startActivity(Activity.java:4181)
at com.MyActivity.openCalc(MyActivity.java:202)
at com.MyActivity.onOptionsItemSelected(MyActivity.java:191)
at android.app.Activity.onMenuItemSelected(Activity.java:2914)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:408)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
at android.app.ActivityThread.main(ActivityThread.java:5461)
It seems like the way, that documentation points to doesn't work. Nevertheless, this code will normally open default calculator app.
Intent intent = new Intent();
intent.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");
startActivity(intent);
The above answer works, but it does not answer the question. The question is how to launch a calculator implicitly via a category. The stock calculator (not the google play version) has the following in the manifest:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_CALCULATOR" />
</intent-filter>
The problem is simple. If the intent filter is modified as shown below the calculator can be started (tested on Pixel2 running 8.1):
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_CALCULATOR" />
</intent-filter>
The DEFAULT category is required (and this is clearly documented). The problem is an app that wants to start the activity has no control of the manifest in the target activity.
Related
so I have an application with multiple activities. So when I switch from 1 activity to another and then click on the back button it works fine. But when I click on 1 activity then go out of the app and go back, it removes the main activity from memory so when you click on the back button, nothing happens. There are 2 possible solutions here, if there is somehow someway to detect if an activity is out of memory or if I can save the activity in memory. This is how I open the activity:
Intent intent = new Intent(context, QuoteActivity.class);
Gson gson = new Gson();
String quoteDataAsAString = gson.toJson(quoteData);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("QuoteData", quoteDataAsAString);
context.startActivity(intent);
And these are the 2 activities:
<activity
android:name=".MainActivity"
android:launchMode="singleInstance"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".quote.activity.QuoteActivity"
android:launchMode="singleInstance"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".user.UserFeedBackActivity"
android:launchMode="singleInstance"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
This is what I have in the main view:
#Override
public void onStart() {
super.onStart();
if (QuoteActivity.isChangedWithFavourites()) {
gridView.setAdapter(new QuoteImageAdapater(getApplicationContext(), reader.getCorrectData(currentSection), section));
QuoteActivity.setChangedWithFavourites(false);
}
}
A gif showing it: https://i.imgur.com/YZIkBU1.gifv
And this is how it should be: https://i.imgur.com/hghjB9L.gifv
This problem occurs on both activities even when I don't call the finish method.
Edit: I figured it out I had to change launchMode to singleTop
In Application class, You can override onLowMemory() method.
The documentation says,
This is called when the overall system is running low on memory, and actively running processes should trim their memory usage. While the exact point at which this will be called is not defined, generally it will happen when all background process has been killed. That is, before reaching the point of killing processes hosting service and foreground UI that we would like to avoid killing.
When OnLowMemory is called, Using EventBus you can trigger an event which should be caught by your Activity. Upon which you can perform your desired action.
If you looking to find, If the Activity has encountered OutOfMemoryException(OOM), then follow this answer.
How do I discover memory usage of my application in Android?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So basically I am creating a very simple app that has only 2 layouts and I want to go from one to another properly. I know from what I have read that if you want to create a new screen/activity on the same project, you first have to create the new layout (which I already did), and I know that now I have to create the activity and do something to the manifesto, but I do not know what that is. I have seem some youtube videos about but I do not know if the fact that if I want my new activity to be the default one changes anything.
As you will be able to see in the attached pictures, "activity_questions" was the first layout that I had back when I created the project. Now I want to create a new screen/layout for the app which is the "noquestions_layout" one. However, I want to make the new layout that I created my main screen/activity for the user, and my "activity_questions" the one that will pop whenever my database feeds some information to the app.
How can I do all this? I know this is one of the things that you only need to learn once...and this might sound very simple, and I apologize if is something newbie. I basically started to learn android studio not too long ago.
You do not need to tell me all the code that I need to put in my app, just some basic examples with guidance... "create Y here, and then put X there"
For new screen layout create a new activity and call that layout file there.
To make any activity as your first activity when app starts, you have to go to manifest and cut paste the intent filter tag to the activity you want to start first
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Suppose you want to make another activity example .SecondActivity as starting activity cut above intent filter tag and paste it there like this
<activity android:name=".SecondActivity ">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity ">
</activity>
First Create two Activities, Say, Activity_A and Activity_B.
For the first activity, place this code in the manifest:
<activity android:name=".Activity_A">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
For the second activity, use this code:
<activity android:name=".SecondActivity ">
</activity>
Here, the Activity that launches when the app starts is the Activity_A, because of the intent filter in the manifest of the Activity_A:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Now, Since you already have your Activities, the layouts ready, where Activity_A is started as soon as the app is started, to launch Activity_B from Activity_A, use this code:
Intent intentTour = new Intent(Activity_A.this, Activity_B.class);
intentTour.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); //This line is optional, better to use it because it won't create multiple instances of the launching Activity.
startActivity(intentTour);
When you create a new activity in Android Studio, Studio will create the corresponding resource file as well as manifest entry for your activity.
Say for example, you have two activities QuestionsActivity and NoQuestionsActivity. QuestionsActivity will be your default launch activity. To make NoQuestionsActivity your launch actvity. Open the manifest file and under activity tag of NoQuestionsActivity include the intent filter and remove intent filter from
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".QuestionsActivity"></activity>
<activity android:name=".NoQuestionsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
To switch from one activity to another, say from NoQuestionsActivity to QuestionsActivity use intent the following code-
Intent questionsIntent = new Intent(NoQuestionsActivity.this, QuestionsActivity.class);
startActivity(questionsIntent);
If you want to pass value to QuestionsActivity pass it as extras in the intnet.
Hope this will help.
I have a little mystery here, I have this code in my onCreate method:
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Log.i(TAG, "ACTION_VIEW START");
Uri uri = intent.getData();
SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();
tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
tEditor.putString("GuestSurname", uri.getQueryParameter("a"));
tEditor.apply();
//it shows an alert to the user
GuestLogin(uri.getQueryParameter("h"), uri.getQueryParameter("a"));
Log.i(TAG, "ACTION_VIEW END");
}
And I have this code in my manifest:
<activity
android:name="epinom.jm.smarthotel.vcMainScreen"
android:label="#string/title_activity_home"
android:launchMode="standard"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="epinom.jm.smarthotel.vcMainScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<data android:scheme="com.guestperience" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And from a web page I'm executing this JS:
window.location = "com.guestperience://?h=x&a=x";
So here comes the funny part, if I plug my phone, and then in Android Studio, I click on the Play or Debug button, and then I go to the Mail App and tap over a hyperlink that takes me to my web page in Chrome that have the JS instruction, it opens My App and open the intent using the onCreate and onStart method like I expect and add it to the stack of intents in My App, this means that if I'm on any intent of my app and I execute the JS, the app comes to the front and it creates the intent and do what it is supposed to do and shows an alert to the user.
But if I pull the plug or I use the .apk that I have in the Play Store in Beta, this functionality does not work, and I don't understand the difference because to me is the same code, so this is what happens when I'm not connected to Android Studio:
If the app is close, I click on the link, it opens Chrome and the the app is started, and the first intent of the app that is the same that I'm calling, do what it is supposed to do and shows the alert.
Once the app is open if I repeat the steps it never shows the intent and it does not matter if I'm in the initial intent or in another intent.
I have tried to change the code to the onStart but it is almost the same behavior:
If the app is close, I click on the link, it opens Chrome and the the app is started, and the fist intent of the app that is the same that I'm calling, do what it is supposed to do and shows the alert.
Once the app is open if I repeat the steps it only shows the alert when I'm in the main intent (the same that I'm calling), if I'm in another intent it never shows the intent, but if I navigate to the intent the Alert is shown every time I call it. (on every onStart, this can be controlled with a bool).
At the end, I don't understand why the behavior is different when I'm plugged to Android Studio.
Maybe is some permission that I'm missing or something that I have to configure, but I'm lost.
Any help will be appreciated.
Thanks.
UPDATE 1:
I have detected this:
If I plug the phone and press play and keep the plug everything works like a charm.
If I plug the phone and press play and remove the plug everything works like a charm.
If I plug the phone and press play and close the app (the plug can be plugged or not) if I start the app with the link works like a charm, but if the app is started stops working on any intent.
There is something that Android Studio is doing that makes it work, I'm thinking that it has to be with permissions but I'm really lost.
UPDATE 2:
I have tried all the options of this examples and I still have the same result, if the app is open i can't get to the intent, but if the app is closed or is plugged to Android Studio works like a charm.
<!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" android:host="guestperience.com" android:path="/Main"/>
</intent-filter>
<!-- Support zxing://scan/?... like iPhone app -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="com.guestperience" android:host="Main" android:path="/"/>
</intent-filter>
I have tried to attach it to the launcher intent and nothing seems to work.
<category android:name="android.intent.category.LAUNCHER"/>
I have tried to launch the app from an href, to see if a user action is needed and still the same result.
CLICK HERE TO LOGIN
https://developer.chrome.com/multidevice/android/intents
https://github.com/zxing/zxing/blob/master/android/AndroidManifest.xml
UPDATE 3:
I have added this to track the action that is called once the app is open:
Log.i(TAG, intent.getAction().toString());
If I open my app for the first time the value is:
"com.guestperience://Main/"
But if I open another intent and open the app through the link again the result is the last action I have called i.e.:
"epinom.jm.smarthotel.vcMainScreen"
And of course if I open the app with Android Studio I always get this value:
"com.guestperience://Main/"
Because all the app is configurable through JSON files all my activities have intent filters so all my calls are like:
Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen"); //replacing this "epinom.jm.smarthotel.vcMainScreen" with the JSON string var of course
startActivity(tIntent);
finish();
I have read this too, and as far as I can tell I'm not missing anything:
http://developer.android.com/intl/es/training/app-indexing/deep-linking.html
After doing a lot of tests and reading a lot, I have ended doing a base class that extends Activity and my Main Activity extends from the Base Activity.
public class BaseActivity extends Activity {
}
public class vcMainScreen extends BaseActivity {
}
Then on the onStart() of the Base Activity I have added this code to handle the call from the browser:
#Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();
tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
tEditor.putString("GuestSurname", uri.getQueryParameter("a").replace("/",""));
tEditor.apply();
Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen");
tIntent.putExtra("Login", "true");
startActivity(tIntent);
finish();
}
}
As you can see it calls the Main Activity an there in the onStart() I have added this lines to call my login method:
#Override
protected void onStart() {
super.onStart();
if (getIntent().getExtras() != null && getIntent().getExtras().getString("Login") != null && getIntent().getExtras().getString("Login").equals("true")) {
SharedPreferences tPrefs = getSharedPreferences("UserFormPreferences", MODE_PRIVATE);
GuestLogin(tPrefs.getString("GuestRoomNumber", ""), tPrefs.getString("GuestSurname", ""));
getIntent().putExtra("Login", "false");
}
}
And in the Manifest I have added this code:
<activity
android:name="epinom.jm.smarthotel.BaseActivity"
android:label="#string/title_activity_home"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<data android:scheme="com.guestperience" android:host="Main" android:path="/"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="epinom.jm.smarthotel.vcMainScreen"
android:label="#string/title_activity_home"
android:launchMode="standard"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="epinom.jm.smarthotel.vcMainScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Is important that the Base Activity has a launchMode="singleTask", and a the end I have to use a URL like this:
CLICK HERE TO LOGIN
And I'm using this GIT to handle my DeepLink with some changes:
https://github.com/hampusohlsson/browser-deeplink
I'm sure that this is not the correct way of doing this, but I hope this helps someone in the future.
Happy coding to all.
When someone clicks on a link in a webpage of form "com.foo.bar://testtest" I want it to open my unity game and for me to get the testtest data.
I'm an experienced programmer, but when it comes to android I kind of google my way around rather than really understanding anything. Bare that in mind. :)
I can react to links on android using intent-filters. However all the resources I've found have assumed you can extend your main activity to capture the new intent. It's possible to do that with unity, but for various reasons I'd rather not. I tried creating a new activity, exporting it to a jar, and adding this to my manifest in the application tag:
<activity android:name="com.foo.ProtocolCatcher"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="com.foo.bar" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
Clicking on a link successfully launches my game, but onto a black screen.
Edit: I've also tried this format to no change:
<activity android:name="com.foo.ProtocolCatcher"
android:label="#string/app_name">
<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="com.foo.bar" />
</intent-filter>
</activity>
What are the magic incantations to make the whole game boot, along with my custom activity, and let my custom activity read the incoming URL, without touching the main activity?
I suppose that you are missing a part of the boot sequence; the steps required are the following:
Define the ProtocolCatcher Activity with te proper scheme (OK)
Define the MainActivty, which represents your Unity3D game main Activity (OK)
Start the MainActivity when the ProtocolCatcher Activity gets started (MISSING)
Implementing the third step is super easy; just edit your ProtocolCatcher Activity's onCreate() method:
//ProtocolCatcher
//...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
Intent gameIntent = new Intent(this, MainActivity.class);
/*
//Pass the extra data to the game if needed
Intent sourceIntent = getIntent();
Uri data = sourceIntent.getData();
gameIntent.putExtra("uriData", data != null ? data.toString(): null);
*/
startActivity(gameIntent); //start the real game
finish(); //close the ProtocolCatcher activity
}
Considering the fact that you are "injecting" the ProtocolCatcher Activity manually, if you have problem to refer MainActivity from the ProtocolCatcher onCreate() you can lookup the relative Class using reflection.
I have two applications where the one opens by implicit intentthe other one.So in the first application I create an Intent and where I wrote i.setAction("com.example.secondApp");and I launch it through startActivity(i);
Then on the second app I change the manifest(filter) like:
<intent-filter>
<action android:name="com.example.secondApp" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
plus I do all the creation intent in the java section.
*code tested because everything was done by explicit intent in the first place and worked fine
So my point is when I try to run them both the first app installs nicely where the second one says that
No Launcher activity found!obviously cause I changed it but despite it installs it isn't shown on the phone nor the first App detects the second one,any clue?
*Also when I leave the manifest(filter) of the second app at default values it installs fine.
If you want an activity to appear in the launcher, it needs the appropriate <intent-filter>:
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
If you want that activity to have another <intent-filter>, that is fine. An <activity> can have as many <intent-filter> elements as needed.