How to get current activity correctly? - java

I need to access current activity of my app. I checked this official code
If i use this code below as documentation says:
PythonActivity = autoclass('org.renpy.android.PythonActivity')
i can't access activity and it returns error. So after searching i found this:
PythonActivity = autoclass('org.kivy.android.PythonActivity')
There is 2 function below. First one is opening webbrowser just like in documentation and IT WORKS:
from jnius import cast
from jnius import autoclass
PythonActivity = autoclass('org.kivy.android.PythonActivity')
Intent = autoclass('android.content.Intent')
Uri = autoclass('android.net.Uri')
intent = Intent()
intent.setAction(Intent.ACTION_VIEW)
intent.setData(Uri.parse('http://kivy.org'))
currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
currentActivity.startActivity(intent)
Now i need to recode this for my own script. I want to add new contact to Contacts. I got 'WRITE_CONTACTS' permission for that. in buildozer.spec:
android.permissions = WRITE_CONTACTS
But my own script returns me error. My function:
from jnius import autoclass,cast
PythonActivity=autoclass('org.kivy.android.PythonActivity')
Intent = autoclass('android.content.Intent')
JS=autoclass('java.lang.String')
intent=Intent()
intent.setAction(Intent.ACTION_INSERT)
intent.setType('ContactsContract.RawContacts.CONTENT_TYPE')
intent.putExtra('ContactsContract.Intents.Insert.NAME',JS('Example Name'))
intent.putExtra('ContactsContract.Intents.Insert.PHONE',JS('7777777777'))
currentActivity=cast('android.app.Activity',PythonActivity.mActivity)
currentActivity.startActivity(intent)
Log:
jnius.jnius.JavaException: JVM exception occurred: No Activity found
to handle Intent { typ=ContactsContract.RawContacts.CONTENT_TYPE (has
extras) } android.content.ActivityNotFoundException
I don't know that Is this error eccours because of activity or my wrong type selection. I would be glad if anyone help me to handle this. Like this contents on media is very few. So i hope like this topics let people learn quickly just like me.

I don't know the Python syntax, but I can tell you what the problem is:
You are missing the Intent ACTION. You need to set the ACTION in the Intent to ContactsContract.Intents.Insert.ACTION (which has the string value "android.intent.action.INSERT")
Also, it looks like you are sending Android constant names instead of the actual string values of these things, for example:
you do this:
intent.setType('ContactsContract.RawContacts.CONTENT_TYPE')
which sets the type in the Intent to the string value "ContactsContract.RawContacts.CONTENT_TYPE", which you can see here:
jnius.jnius.JavaException: JVM exception occurred: No Activity found
to handle Intent { typ=ContactsContract.RawContacts.CONTENT_TYPE (has
extras) } android.content.ActivityNotFoundException
but the type needs to be set to the Android constant ContactsContract.RawContacts.CONTENT_TYPE which has the string value "vnd.android.cursor.dir/raw_contact"
As I said, I don't know Python syntax, but you probably need to do something like this:
intent=Intent()
intent.setAction(ContactsContract.Intents.Insert.ACTION)
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE)
or, if Python supports it, Intent has a constructor that takes an ACTION as a parameter, so this might also work:
intent=Intent(ContactsContract.Intents.Insert.ACTION)
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE)
Let me know if any of this makes sense.

FINALLY, I found solution to access activities and getting Contacts datas.
Accessing correctly PythonActivity:
PythonActivity = autoclass("org.kivy.android.PythonActivity")
Accessing Contacts Java Class:
Contacts = autoclass("android.provider.ContactsContract$Contacts")
Accessing ContactsContract.CommonDataKinds.Phone Java Class (same):
Kinds = autoclass("android.provider.ContactsContract$CommonDataKinds$Phone")
Creating getContentResolver():
cr = PythonActivity.mActivity.getContentResolver()
Now we need to create 2 query. In first, we are going to find ID and need to use it in second query to find equal NUMBER. Also need to check is contact has phone number? too. After that we can loop second query to find number:
name_number_dict= {} # Name:Number # Change as you wish..
while (que1.moveToNext()): #Query 1 Loop
if que1.getString(que1.getColumnIndex(Contacts.HAS_PHONE_NUMBER)): #If has number
que2 = cr.query(Kinds.CONTENT_URI, None, Kinds.CONTACT_ID + " = " + que1.getString(que1.getColumnIndex(CONTACTS_ID)), None, None) #Query 2 Loop
while (que2.moveToNext()):
name_number_dict[que1.getString(que1.getColumnIndex(Contacts.DISPLAY_NAME))] = que2.getString(que2.getColumnIndex(Kinds.NUMBER) # Get datas and put in dic.
If you need to check all ColumnNames of query, use query1.getColumnNames() >> Referance
I hope it helps you guys who need to use this in Python>Kivy applications..

Related

android.os.TransactionTooLargeException when executing queryIntentActivities

I am using a device with Android 5.0.1 and when execute the function:
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent,0);
An exception of type TransactionTooLargeException is thrown ....
I cannot use the flag: MATCH_DEFAULT_ONLY because I can't be limited to only those activities that support the CATEGORY_DEFAULT.
Looks that the problem is related with the amount of data returned, like many related issues that I found here at stackoverflow ...
Is there a way to break this response? Or is there a query, equivalent, or a combination of flags that allow get the same results making more than one query?
I am asking because is not clear to me the meaning of flag = 0 in documentation: https://developer.android.com/reference/android/content/pm/PackageManager.html#queryIntentActivities(android.content.Intent, int)
May be I can query more than once, with different queries, and combine the results?
You could chunk your query by being a bit more specific with how you form your Intent, and do multiple queries rather than 1 lump sum query. Right now, you're querying basically every application (potentially multiple for each) on the device (since everything that can launch will have a android.app.action.Main action), which goes over your allocation of the ~1 MB shared buffer parcel limit causing the exception:
From the docs:
{ action=android.app.action.MAIN } matches all of the activities that can be used as top-level entry points into an application.
{ action=android.app.action.MAIN, category=android.app.category.LAUNCHER } is the actual intent used by the Launcher to populate its top-level list.
So, adding a category narrows the search results. If you need everything of action type "android.app.action.Main", use that as the action, then iterate over an additional set of categories ex sudo code:
List<ResolveInfo> activities = new ArrayList<ResolveInfo>()
String[] categories = new String[] { android.app.category.LAUNCHER, additional... }
for(String category: categories){
Intent mainIntent = new Intent(Intent.ACTION_MAIN)
mainIntent.addCategory(category)
List<ResolveInfo> matches = manager.queryIntentActivities(mainIntent, 0); //You might want to use a better #ResolveInfoFlag to narrow your ResolveInfo data
if(!matches.isEmpty()){
activities.addAll(matches)
}
}
You should also probably do a try catch, because when doing a MATCH_ALL, there's still no guarantee that the query won't be too large. There might be appropriate flags to help with this, but I'm not familiar with your use case.

Android Studio - URL string

So I'm pretty new to the whole Android Studio thing and I've been using the internet to help me with a lot of the things I am doing and needed help on something.
I'm not sure if it's possible to connect this to either a string or an SQL database but I have a Main Layouts with a bunch of buttons that allow me to click on them and choose what external player I would like to use to watch the video. In my MainActivity java class, this is how it finds the button.
case R.id.button3:
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("http://videoname.mp4"), "video/*");
startActivity(Intent.createChooser(intent, "Choose an External Player"));
break;"
I wanted to know if "http://videoname.mp4" url can be connected to like a string where I can always update or change the URL instead of manually going to find the URL in the MainActivity java and changing it. As of now I have to manually do it but a different way to do it would be helpful.
I'm sorry if it's all confusing, but if you know, please let me know as soon as.
Thank you.
you just need write your string URL :
open your directory folder /res/values/strings.xml -> write your string : <string name="yourStringName>yourStringURL</string>. to use your string do this
getContext().getString(R.string.yourStringName) in fragment
getString(R.string.yourStringName) in Activity
or you can write directly on your code, put your cursor on your string, then press key alt + enter choose extract string resource fill the resource name with your string name
wherever you need to use it, just do point 1 or 2. also in your Intent
hope this help you, never stop learning!
Add it to strings.xml in your project. That is the recommended way of using strings anyway.

Opening apps on buttons

Im trying to open. Google Search on my application. But the problem is. when I click the button. the COMPLETE ACTION USING windows is popping up instead of the google search.. search the net for more than an hour but it seems I cant find the solution.. here is my code..
#Override
public void onClick(View view) {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(ComponentName.unflattenFromString("com.google.android.googlequicksearchbox"));
intent.addCategory("android.intent.category.LAUNCHER");
startActivity(intent);
This is due to Android's nature to allow users to make their own decisions. If, for instance, they have Bing installed and prefer it as a search engine over Google, they will have the option to select it. As far as I know, there is no way to open a specific app this way. If the user selects Google and makes it the default app for this action, it will auto-open in successive times, but they must make that conscious decision first.
have you probably tried to follow this guide..?
It describes well about what you might need..
hope it helps..
List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(intent, 0);
for(int i = 0; i < resolveInfoList.size(); i++) {
ResolveInfo info = resolveInfoList.get(i);
if (info.activityInfo.packageName.equals("com.google.android.googlequicksearchbox") {
// that's the one you want
}
}
I don't have Eclipse available right now to test it, but this should help you get there. Also check out the documentation for queryIntentActivities()
PS: I'm not sure about that packageName for google search
Try this. This code will search the meaning of value of query variable on google.
String url = "http://www.google.com/search?q=" + "Meaning of " +query;
Intent intentSearch = new Intent(Intent.ACTION_VIEW);
intentSearch.setData(Uri.parse(url));
startActivity(intentSearch);

Trying to pass an int between two classes on Android platform

I'm trying to pass an int between two classes using a bundle. I have looked online and it seems like it should be easy to do, its just not working for me :( any help is much appreciated! I am trying to pass the int life from one page to another in a simple game.
here is the code for the first page where I am passing it from
int life = 5;
....
if(input.equalsIgnoreCase(teststr))
{
Intent i = new Intent("com.name.PAGETWO");
i.putExtra("com.name.PAGETWO.life", life);
startActivity(i);
mpButtonClick.stop();
}
And on the second page, trying to receive the int
Intent i = new Intent("com.name.PAGETWO");
Bundle extras = i.getExtras();
int temp2 = extras.getInt("life");
int life = temp2;
when i try to run it, it tries to go on to the second page and then just says the application has unexpectedly stopped, but when i comment out the code it continues running as normal, so i know i am definitely putting in the code here wrong somewhere. thanks in advance!
Why would a brand new intent object contain the int you've passed? In the receiver activity, use getIntent() to retrieve the intent that the activity was started with. That intent would contain your extras.
You're creating a brand new Intent on the second page, which of course doesn't have the bundle. Instead, you need to retrieve the calling Intent using getIntent().
Here's how your second page's code could look:
int life = getIntent().getExtras().getInt("life");
EDIT: Looking at your code again, make sure the key name of the extra is consistent on both ends. To be sure, I usually use a final variable for this. So in your second activity (let's say it's ActivityTwo), declare this at the top (outside of onCreate()):
final static public String EXTRA_LIFE = "life";
Then in the calling activity:
Intent i = new Intent(this, ActivityTwo.class);
i.putExtra(ActivityTwo.EXTRA_LIFE, life);
startActivity(i);
(You may have also been constructing your Intent incorrectly; compare my example).
And in the second activity, inside of onCreate():
int life = getIntent().getIntExtra(EXTRA_LIFE, 0);
(You can replace 0 with what you want the default value to be if the extra doesn't exist.)
That way you don't have to worry about typos and can rely on Eclipse's suggestions to make sure you're consistent.

Unable to pass values between Activities in Android

I am using 2.3.3 version of the Android SDK and I'm trying to pass data between two activities using the following code
Intent myIntent = new Intent(MainAct.this, FriendsActivity.class);
myIntent.putExtra(USER_NAME, ((EditText)findViewById(R.id.username)).getText());
MainAct.this.startActivity(myIntent);
In the FriendsActivity i'm retrieving the value using
Bundle b = getIntent().getExtras();
String user = b.getString(MainAct.USER_NAME);
But the user is null after these lines are executed. Not sure whats wrong here. Read similar questions on SO http://goo.gl/zOJfa but still the problem continue to be seen.
You need to pass (EditText)findViewById(R.id.username)).getText().toString() instead. getText() on an EditText View doesn't return a string, it returns an Editable Object.
just do (EditText)findViewById(R.id.username)).getText().toString() you are able to get string value.

Categories