I have this following code, in Class named Menu which extends from ListActivity.
When I click on listitem the Toast line is getting executed properly but nothing happens after that, I guess code in catch block is getting executed and that Intent part is throwing some exception. Do you see any problem with this definition ?
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
try {
Toast.makeText(Menu.this, "Clicked!!", 5000).show();
Class myClass = Class.forName("com.palye.first.MainActivity");
Intent menuI = new Intent(Menu.this, myClass);
startActivity(menuI);
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
You do know if you own the Activity you can create an explicit intent:
Intent intent = new Intent(Menu.this, MainActivity.class);
then you don't need the try catch either
Sometimes the
Class myClass = Class.forName("com.example.first.MainActivity");
isn't enough, because it will not load the class. I need to make a myClass.newInstance(); and than use the myClass, even if I am not using the created object.
Try it , maybe it will solve your problem.
Why don't you try MainActivity.class instead? e.g., Intent menuI = new Intent(Menu.this, MainActivity.class);
Can you post the logcat output?
Somewhere I saw a few package names are excluded from loading, deploying, forgot which ones. As I remember one is the "android" other is the "internal" or "example" . Because I am switching / mixing the iOS / Android / Java EE I am not sure where isn't allowed and which one.
Try to rename / refactor the "example" to "my" package, maybe it will solve. For Android Market for sure isn't allowed to deploy with "example"
Related
Im trying to implement MVVM architecture using ViewModel and LiveData. These two methods are inside a Activity:
private void handleResult(BoardViewModel vm) {
vm.getLiveDataSingleObj("Result").observe(this, new Observer<Object>() {
#Override
public void onChanged(#Nullable Object resultObj) {
Result result = (Result) resultObj;
if (!result.isCompleted()) return;
gotoResult();
}
});
}
And
private void gotoResult() {
Log.w(LOG_TAG, "Result: Moving to next activity");
Intent intent = new Intent(boardActivity, ResultActivity.class);
intent.putExtra("LEVEL", levelIndex);
intent.putExtra("MAP", mapIndex);
startActivity(intent);
}
The handleResult method is setup to listen for result objects that indicate that the game has ended and it is time to move on to the next activity ("gotoResult"). However, this completely breaks the navigation of the app, when i go back and then say attempt to start a new game session i instead instantly go to the next activity telling me I've already won.
Any ideas as to why it fires multiple times and eventually stops, letting me start a new session. To clarify, if I remove the gotoResult the logic works every single time no errors with indexes out of bounds or what have you, it's only when I add the goto that everything breaks.
ViewModel:
private void setupHashTypes() {
hashLiveData.put(KEY_BOARD, liveDataBoardQuery);
hashLiveData.put(KEY_STEPS_COUNTER, game.getStepsTakenLiveData());
hashLiveData.put(KEY_PATH_CHANGE, game.getPathChangedLiveData());
hashLiveData.put(KEY_VALUE_CHANGE, game.getValueChangeLiveData());
hashLiveData.put(KEY_TIMER, game.getTimerLiveData());
hashLiveData.put(KEY_SELECTED, game.getSelectedLiveData());
hashLiveData.put(KEY_DESELECTED, game.getDeselectedLiveData());
hashLiveData.put(KEY_HOLD, game.getHoldLiveData());
hashLiveData.put(KEY_UNHOLD, game.getUnholdLiveData());
hashLiveData.put(KEY_RESULT, game.getResultLiveData());
}
public LiveData<Object> getLiveDataSingleObj(String type) {
if (hashLiveData.containsKey(type)) {
return (LiveData<Object>) hashLiveData.get(type);
}
throw new IllegalArgumentException("Invalid: key was not found: " + type);
}
And the Model has getters, example:
private final SingleLiveEvent<Result> resultLiveData = new SingleLiveEvent<>();
public LiveData<Result> getResultLiveData() {
return resultLiveData;
}
you should remove the observer in onDestroy() method
Changing from MutableLiveData which always resends the previous set values to new subscribers, to SingleLiveEvent which doesn't have this behaviour, solved the problem.
The class can be found here: https://github.com/googlesamples/android-architecture/tree/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp
I'm a bit confused on Intents.
Why is
Intent implicit=new Intent(IDownload.class.getName());
an Implicit intent
while
Intent explicit=new Intent(implicit);
is an Explicit intent while it doesn't seem to add anything new in its definition. The system doesn't seem to draw any new information that wasn't previously provided by implicit intent above?
In the Android documentation (Intent types),
Explicit intents specify the component to start by name (the fully-qualified class name). You'll typically use an explicit intent to start a component in your own app, because you know the class name of the activity or service you want to start......
Intent implicit=new Intent(IDownload.class.getName()); seems to fulfill this requirement, but is still regarded as an Implicit intent, which as per the documentation:
Implicit intents do not name a specific component, but instead declare a general action to perform, which allows a component from another app to handle it.....
Intent explicit=new Intent(implicit); seems to contradict this, but is still regarded as an Explicit intent.
UPDATE - Sample implementation
ref : Binding to a Service
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
appContext=(Application)getActivity().getApplicationContext();
Intent implicit=new Intent(IDownload.class.getName());
List<ResolveInfo> matches=getActivity().getPackageManager()
.queryIntentServices(implicit, 0);
if (matches.size() == 0) {
Toast.makeText(getActivity(), "Cannot find a matching service!",
Toast.LENGTH_LONG).show();
}
else if (matches.size() > 1) {
Toast.makeText(getActivity(), "Found multiple matching services!",
Toast.LENGTH_LONG).show();
}
else {
ServiceInfo svcInfo=matches.get(0).serviceInfo;
try {
String otherHash=SignatureUtils.getSignatureHash(getActivity(),
svcInfo.applicationInfo.packageName);
String expected=getActivity().getString(R.string.expected_sig_hash);
if (expected.equals(otherHash)) {
Intent explicit=new Intent(implicit);
ComponentName cn=new ComponentName(svcInfo.applicationInfo.packageName,
svcInfo.name);
explicit.setComponent(cn);
appContext.bindService(explicit, this, Context.BIND_AUTO_CREATE);
}
else {
Toast.makeText(getActivity(), "Unexpected signature found!",
Toast.LENGTH_LONG).show();
}
}
catch (Exception e) {
Log.e(getClass().getSimpleName(), "Exception trying to get signature hash", e);
}
}
}
The linked example includes these lines
Intent explicit=new Intent(implicit);
ComponentName cn=new ComponentName(svcInfo.applicationInfo.packageName,
svcInfo.name);
explicit.setComponent(cn);
The first line simply creates a new Intent instance that's a copy of the old one. While the variable might be explicit, at this point in time, it is still an implicit intent.
The second line creates a ComponentName object based on the single matching result from an earlier getActivity().getPackageManager().queryIntentServices(implicit, 0) call. At this point, explicit is still an implicit intent.
The third line is the magic. Once the specific ComponentName is assigned to the Intent instance, explicit truly becomes an explicit intent.
I'd like to start a WebView from my AsyncTask but it doesn't seem to run. This is what my onPostExecute method looks like:
public class Viewer extends AsyncTask<URI, Integer, URI> {
private Activity objContext = null;
public Viewer(Activity objContext) {
this.objContext = objContext;
}
protected void onPostExecute(URI uriWebpage) {
WebView wbvBrowser = new WebView(this.objContext);
wbvBrowser.getSettings().setBuiltInZoomControls(true);
wbvBrowser.getSettings().setJavaScriptEnabled(true);
wbvBrowser.loadUrl(uriWebpage.toString());
}
}
My task is used by two activities in my application and therefore my global objContext variable is of type Activity. If I change the type of my objContext variable to the name of the calling class, it works fine but then I can't instantiate my task from the other calling class. I instantiate my task like this.
Viewer mytask = new Viewer(this);
How can I solve this?
Did you setContentView from original layout to webView or you have a container to put webview? otherwise I don't think webView UI appears.
Are you sure you execute your AsyncTask
#Override
protected void onPostExecute(Void result){
}
}.execute();
Also need to class name
Viewer mytask = new Viewer(YourclassName.this);
// or This may Helps you
private Context mcontext;
public Viewer(Context objContext) {
this.mcontext= objContext;
}
protected void onPostExecute(URI uriWebpage) {
WebView wbvBrowser = new WebView(((Activity)(mcontext)));
}
I have solved the issue. It has nothing to do with the use of Activity or Context. Both work just fine. Some URLs don't seem to load the WebView. I changed the URL of the WebView to point to a site like Google and it worked just fine. Seems like if the URL is incorrect, the WebView doesn't throw an exception but doesn't open up either.
I don't know why this happens, but why don't you just start the built in web browser through an Intent in your onPostExecute(Uri uriWebpage)?
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uriWebPage);
startActivity(intent);
If this solution doesn't satisfy you, then please post the error stack trace from LogCat.
I'm having a problem with an android application that I'm working on.
My application has several sections and the next screen that loads is based on a string. So, screen 1 of section 1 would be, S1S1.
My question is, how can I start an activity based on a string. I have S1S1 saved in a string, let us call it next activity. Rather than having to type S1S1.class, I need it to come from the string. I've tried everything I can think of and google hasn't helped much.
Some things I've tried are
Intent myIntent = new Intent(nextactivity);
Intent myIntent = new Intent(v.getContext(), getClass().getName().valueOf(nextactivity));
Intent myIntent = new Intent(v.getContext(), Class.forName(nextactivity));
and tried running with
startActivityForResult(myIntent, 0);
but nothing seems to work. Any ideas?
Here is a code by which you can start activity using the name of the activity
String activityToStart = "com.example.MainActivity";
try {
Class<?> c = Class.forName(activityToStart);
Intent intent = new Intent(this, c);
startActivity(intent);
} catch (ClassNotFoundException ignored) {
}
EDIT
Here class name will be full name of the class with the package name.
For example if your package name will be x.y.z and if you have Activity name called A then the full name of the Activity A will be x.y.z.A.
An even better way (and one that is used in the system to launch Browser.apk along with other apps that aren't bundled with AOSP):
Intent intent = new Intent();
intent.setClassName("com.android.browser","com.android.BrowserActivity");
context.startActivity(intent);
Alternatively, if you want to check that you can start the Activity from the command line, you can do something like this from your shell:
adb shell
am start com.android.browser/.BrowserActivity
I am not aware of solution but i have an alternative.. the way similar to div hide and show in web pages.
if your s1s1 is to loaded low content have them in a linearlayout and keep their visibility gone on loading form s1. when you click on s1 to reach s1s1 hide s1 and set the params of visibility to "visible".
By doing this you can avoid creating a separate activity and this way is also easy to navigate back.
Use Enums!
public enum SectionActivity {
S1S1(MyS1Activity.class),
S1S2(S2Activity.class);
private Class<? extends Activity> activityClass;
private SectionActivity(Class<? extends Activity> clazz) {
this.activityClass = clazz;
}
public Class<? extends Activity> getActivity {
return activityClass;
}
}
Then somewhere in your code:
SectionActivity act = SectionActivity.valueOf(string);
Intent intent = new Intent(this, act.getActivity());
startActivity(intent);
I'm developing a lite version for an app on the Android. How can I start an Intent to open the Android Market, preferably with the full version of my app displayed? This is difficult to test on an emulator (which is the closest thing to a device I have), as there seems to be no legal way of installing the Market on it.
That query above works, but when I tried it, it looked like it was bringing up search results based on the name.
If you use something like
intent.setData(Uri.parse("market://details?id=com.wolinlabs.SuperScorepad"));
instead, it will go right to the Android Market page for your app.
I think that's more what you wanted (?)
Found answer in the end:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://search?q=pname:MyApp"));
startActivity(intent);
No way of testing on emulator, though.
Hi I was trying the achieve the same but with one small difference
I DIDN'T WANT TO OPEN IT EMBEDDED ON MY APP
public void start(JSONArray args, CallbackContext callback) {
Intent launchIntent;
String packageName;
String activity;
String uri;
ComponentName comp;
try {
packageName = args.getString(0); //com.android.vending
activity = args.getString(1); //com.google.android.finsky.activities.LaunchUrlHandlerActivity
uri = args.getString(2); //'market://details?id=com.triplingo.enterprise'
launchIntent = this.cordova.getActivity().getPackageManager().getLaunchIntentForPackage(packageName);
comp = new ComponentName(packageName, activity);
launchIntent.setComponent(comp);
launchIntent.setData(Uri.parse(uri));
this.cordova.getActivity().startActivity(launchIntent);
callback.success();
} catch (Exception e) {
callback.error(e.toString());
}
}
THE BIG DIFFERENCE HERE IS THAT YOU START A NEW APP NOT JUST SHOW GOOGLE PLAY IN YOUR
APP
This code is part of a Cordova plugin but is pretty obvious what you need to do to use it natively.
THE IMPORTANT LINES
launchIntent = this.cordova.getActivity().getPackageManager().getLaunchIntentForPackage(packageName);
comp = new ComponentName(packageName, activity);
launchIntent.setComponent(comp);
launchIntent.setData(Uri.parse(uri));
Regards