So my app is saving the names of Bluetooth devices the user has connected to previously in SharedPreferences which is than compared to all of the names of currently paired devices so on opening the app can instantly connect to the said device. This is done by this piece of code:
sharedPreferences = getApplicationContext().getSharedPreferences("BtNames", MODE_PRIVATE);
keys = sharedPreferences.getAll();
for(BluetoothDevice device : pairedDevices) {
try {
for (Map.Entry<String, ?> entry : keys.entrySet()) {...}
This loops through the paired devices and the entries of SharedPreferences whose value than is accessed by this code:
String device_name = device.getName();
String name = entry.getValue().toString();
Now both of these work well and entry.getValue()... returns the exact names of the previously connected devices. The problem occurs when trying to compare the two Strings by:
device_name.equals(name)
This returns false even though both of the Strings appear to be exact same when logged:
E/FaceTracker: EV3LO
E/FaceTracker: EV3LO
I have already tried to replace all spaces with nothing but that didn't work either. Maybe I overlooked something but at the moment I don't really have a clue what's going wrong.
Thanks in advance for answers.
The problem is a non printable and non ASCII character at the end or the beginning of the string. Please try the following script:
name.replaceAll("\\P{Print}","");
I hope it helpem and good luck if it didn't
Related
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..
I found a problem with Shared Preferences which happens only for some devices and only with Android 9 (Pie) o above.
To encrypt my database I create a key and store it to my sharedPreferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String content = sharedPreferences.getString(-nameOfTheKey-, "");
if (content == null || content.isEmpty()){
// Create and store the new key
content = restoreApplicationKey(context);
}
As you can see, first I check for the availability then I create if not exist or empty. This key isn't created in any other place. That is the only point.
When I try to first install the app on my device, the condition return false because the key-value is already present in my SharedPreferences. This is impossibile!
I found online that the solution is to set allowBackup="false" into the Manifest and reinstall the app but I don't understand this behavior. How is it possible that the kay-value is pre setted?
Also, before setting allowBackup to false, I noticed that if forcing the initialization and uninstall the app, after the reinstall the key is still present but the value is changed. Every time with the same string but different from the saved one. All others key are fine, except this one.
As I said, the above code is the only entry point and it's called only at the app launch. Also the restoreApplicationKey(context) is called only at this point.
I understand what SharedPreferences do but still struggling to get my head round what this piece of code is trying to do.
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext());
if (sharedPref.getBoolean("login", false)) {
edtUser.setText(sharedPref.getString("user", ""));
edtPass.setText(sharedPref.getString("pass", ""));
new SigninTask().execute("user=" + edtUser.getText(), "pass=" + edtPass.getText());
}
I understand that the first line is accessing the default SharedPreferences file. However I am still confused, what does this set code do exactly?. What information is it trying to get?. What does the last line do? (new SigninTask())..
sharedPref.getString("user", "") tries to get a preference with the key user from the SharedPreferences. If it's not found, it returns an empty String. This value is loaded to a Text control (I assume, since you didn't include the definition of edtUser).
The same is done with the value of pass, which probably represents a password.
Basically, this app probably stores in SharedPreferences the user and password that were entered by the user of the app in a previous launch of the app, so that the user doesn't have to enter them again every time the app is launched.
There should be additional code that would store the entered user and pass in the SharedPreferences, and store the login preference with the value true.
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.
I am having trouble using and IF statement based on a string from my preferences.
Here is the code:
preferences = PreferenceManager.getDefaultSharedPreferences(this);
String themePref = preferences.getString("theme", "null");
Log.i("Theme", "Current theme is " + themePref );
if (themePref == "dark"){
setTheme(android.R.style.Theme_Black);
}else{
setTheme(android.R.style.Theme_Light);
}
I have two options at this point; light and dark. The code successfully sets themePref as light or dark as needed, and I've confirmed via debugging, but for some reason the if statement fails. I have manually set a string to "dark" and it then works correctly.
Am I missing something here? Why would a string coming from the preferences process any differently?
Any help would be greatly appreciated.
Thanks,
Josh
You should use themePref.equals("dark") (or even better "dark".equals(themePref)) to compare strings. == tells you if the string instances are the same, but two instances can have the same value and not be the same instance.
Is PreferenceManager.getDefaultSharedPreferences(this).getString(...) returning a java.lang.String instance or a subclass? I would replace themePref == "dark" with themePref.equals("dark") instead.