I am using Alert Dialog builder in order to visualize the paired bluetooth devices. I want to pass a sstring array to the setItems() method in order to create the list with the devices. setItems() gets CharSequence[] and a listener. When i pass the string array it fails. How can i fix it? Here is the code:
public void showPairedDevices() {
String[] pairedDevicesArray = new String[100];
// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevicesSet = bluetoothAdapter
.getBondedDevices();
if (pairedDevicesSet.size() > 0) {
int i = 0;
for (BluetoothDevice device : pairedDevicesSet) {
pairedDevicesArray[i] = device.getName();
i++;
}
connectDialog = new AlertDialog.Builder(context);
connectDialog.setTitle("Paired devices");
connectDialog.setItems(pairedDevicesArray, connectDialogClickListener);
connectDialog.show();
} else {
Toast.makeText(context, "No paired devices!", Toast.LENGTH_SHORT)
.show();
}
}
private OnClickListener connectDialogClickListener = new OnClickListener() {
#Override
public void onClick(DialogInterface connectDialog, int button) {
connectDialog.dismiss();
}
};
Your issue stems from the fact that you're starting with a String array that is too big. When you initialize an array of objects, every space is by default null. With that in mind, what you should know is that when you feed an array that is of length 100 to setItem(), it is going to check every index, and if it finds a null it will throw an error. Here is a proposed solution:
public void showPairedDevices() {
// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevicesSet = bluetoothAdapter
.getBondedDevices();
if (pairedDevicesSet.size() > 0) {
// This will set the size of the array to exactly how many you need
String[] pairedDevicesArray = new String[pairdDevicesSet.size()];
int i = 0;
for (BluetoothDevice device : pairedDevicesSet) {
pairedDevicesArray[i] = device.getName();
i++;
}
// ...
}
Related
I am making an android app that asks for the users to select a Bluetooth paired device via spinner.
When the user opens the app first time, user selects a Bluetooth paired device** from list. Then when app opens second time, I want the same Bluetooth paired device to be selected. I don't want user to select the paired device every time the app is opened. How to do that?
Spinner btPairedDevicesSpinner;
BluetoothManager mBluetoothManager;
BluetoothAdapter mBluetoothAdapter;
BluetoothDevice [] mBluetoothDeviceArray;
btPairedDevicesSpinner = findViewById(R.id.btPairedDevicesSpinner);
mGetBluetoothPairedDevice ();
btPairedDevicesSpinner.setOnItemSelectedListener(mPairedDeviceOnItemSelectedListener);
public void mGetBluetoothPairedDevice () {
Set<BluetoothDevice> mPairedDevice = mBluetoothAdapter.getBondedDevices();
mBluetoothDeviceArray = new BluetoothDevice[mPairedDevice.size()];
String [] strings = new String[mPairedDevice.size()];
int index = 0;
if (mPairedDevice.size() > 0) {
for (BluetoothDevice device : mPairedDevice) {
mBluetoothDeviceArray [index] = device;
strings [index] = device.getName();
index++;
}
}
else {
String mOnDevice = "No Device found";
mPairedDeviceArrayAdapter.add(mOnDevice);
}
ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, strings);
btPairedDevicesSpinner.setAdapter(mArrayAdapter);
}
private final AdapterView.OnItemSelectedListener mPairedDeviceOnItemSelectedListener = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
ConnectThread mConnectThread = new ConnectThread(mBluetoothDeviceArray [i], view);
mConnectThread.start();
mBluetoothToolBar.setSubtitle("Connecting");
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
Toast.makeText(BluetoothMain.this, "Nothing is selected", Toast.LENGTH_SHORT).show();
}
};
One way that should work. Store the selected device name in shared preferences. (Create the sharedPref object somewhere else like onCreate() and do the edit in spinners onItemChanged() )
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
sharedPref.edit().putString("btDeviceName", "the name").apply();
After calling
btPairedDevicesSpinner.setAdapter(mArrayAdapter);
load the device name from shared preferences and if there is one call setSelection() on spinner
String deviceName = sharedPref.getString("btDeviceName", null);
if(deviceName != null){
btPairedDevicesSpinner.setSelection(mArrayAdapter.getPosition("deviceName "));
}
I used this Topic
I try this code but did not work :
PACKAGE_NAME = context.getApplicationContext().getPackageName();
try {
pi = context.getPackageManager().getPackageInfo(PACKAGE_NAME, PackageManager.GET_PERMISSIONS);
for (String perm : pi.requestedPermissions) {
Log.e("Foo", perm);
}
} catch (Exception e) {
}
But it could not help me. I have the application list, I want to get the permission that used on each of them.
How can I handle it?
UPDATE:
like the photo, When clicking on "دسترسی ها", I want to get the permission that used in that app.(for example in a telegram: Internet, storage, call, camera,...)
UPDATE 2:
I will share the adapter code for my problem
My Adapter:
class AppViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
AppViewHolder(View itemView, Context context, List<App> apps) {
super(itemView);
txt_show_permission = itemView.findViewById(R.id.txt_show_permission);
/*The String Buffer For Permissions*/
appNameAndPermissions = new StringBuffer();
PackageManager pm = context.getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : packages) {
Log.d(TAG, "App: " + applicationInfo.name + " Package: " + applicationInfo.packageName);
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(applicationInfo.packageName, PackageManager.GET_PERMISSIONS);
appNameAndPermissions.append(packageInfo.packageName + "*******:\n");
//Get Permissions
requestedPermissions = packageInfo.requestedPermissions;
if (requestedPermissions != null) {
for (int i = 0; i < requestedPermissions.length; i++) {
Log.d(TAG, requestedPermissions[i]);
appNameAndPermissions.append(requestedPermissions[i] + "\n");
}
appNameAndPermissions.append("\n");
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
set On Click Listener On txt_show_permission in onBindViewHolder:
holder.txt_show_permission.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showDialog(String.valueOf(appNameAndPermissions));
}
});
Method for dialog in adapter class:
public void showDialog(String txtPermission) {
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.show_permission_dialog);
TextView txt_permission = dialog.findViewById(R.id.txt_permission);
Button btn_ok = dialog.findViewById(R.id.btn_ok);
txt_permission.setText(txtPermission);
btn_ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
You can loop through all the app names and get their permissions and store them in a String Buffer like this:
https://stackoverflow.com/a/14672557/10058326
Or since you want permissions to be shown on button click, you can add for each app the code you have tried with the proper app name in a OnButtonClickListener
Or you can extract the relevant permissions from the StringBuffer made earlier each time the button is clicked
EDIT: See these links on how to create a OnItemClickListener for the Recycler View. You can get the position of the row that was clicked and through that get the app name in that row which you can pass to another function. Then write code inside that function to get permissions for the app name passed and display it
https://antonioleiva.com/recyclerview-listener/
https://hackernoon.com/android-recyclerview-onitemclicklistener-getadapterposition-a-better-way-3c789baab4db
https://gist.github.com/riyazMuhammad/1c7b1f9fa3065aa5a46f
EDIT 2:
Instead of passing appNameAndPermissions to showDialog which contains the whole list, you need to extract permissions of a certain app from the String Buffer. Here's how:
String app_name = itemView.findViewById(R.id.app_name_text_view).getText().toString();
int indexOfApp = appNameAndPermissions.indexOf(app_name);
int indexOfLastPermission = appNameAndPermissions.indexOf("\n", indexOfApp);
String permissions = appNameAndPermissions.substring(indexOfApp, indexOfLastPermission);
So i was making this app which displays an arrayList of different poems
I first request the poems from API then the Asynctask returns the poems in the form of Arraylist i wand to show 20 random poems from the list.
This is the Asynctask code
private class TitleAsynctask extends AsyncTask<URL,Void,List<view>> {
private ProgressDialog progressDialog;
#Override
public List<view> doInBackground(URL... urls){
URL url = Query_utils.createurl(POEM_TITLE);
String json = "";
Log.d(LOG_TAG,"this worked");
{
try {
json = Query_utils.makehttprequest(url);
Log.d(LOG_TAG, "make Httprequest works");
} catch (IOException e) {
}
}
List<view> title_view = Query_utils.extracttitlefromjson(json);
return title_view;
}
#RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onPostExecute(List<view> data) {
madapter.clear();
if (data != null && !data.isEmpty()){
madapter.addAll(data);
}
}
}
and the onCreate code is
TitleAsynctask task = new TitleAsynctask();
URL url = Query_utils.createurl(POEM_TITLE);
task.execute(url);
ArrayList<view > arr = new ArrayList<view>();
final ListView poem_Title_list = (ListView) findViewById(R.id.list_item);
madapter = new title_adapter(this ,arr);
poem_Title_list.setAdapter(madapter);
I can think of two ways:
Just use a random number generator to generate a number between 0 and the number of entries-1. The disadvantage with this method is that you can get repeats.
Randomly sort the list after fetching. You can do this using Collections.shuffle(list) This way you won't get any repeats but you will sort the whole list which could be a waste if there are hundreds of entries and you only want to show 20.
I apologize if I worded this poorly but for the sake of clarity I will explain as best I can. I'm using MPAndroidChart to draw a line graph and I followed this tutorial to get it up and running https://www.numetriclabz.com/android-line-chart-using-mpandroidchart-tutorial/#Defining_X-axis_labels. I've made some adjustments to suit my needs and so on.
On button click, I call a method that adds another entry using the value of the edit text field, at the position that i increment each button press so the code is something like entries.add(new Entry(editTextValue, numEntries));This does what I want it to do while I'm looking at the current activity screen, with the previous value remaining, and the next value being added. However, once i leave that activity and return to it, only the last value remains. My understanding is that I need to have a for loop that will iterate over each element in arraylist when I call the drawGraph method that I'm using, but I haven't had any luck with this. I've tried to use for(Entry e: entries) and use e in place of numEntries, but the data type is not compatible. Any help is greatly appreciated!
EDIT: `public class testActivity extends AppCompatActivity {
int counter = 0;
public ArrayList entries = new ArrayList<>();
public static int lifetimeNums;
public static int nums = 0;
public static int numEntries;
public static String entryLabel = Integer.toString(numEntries);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
reDrawGraph();
}
// Graphing method
public void reDrawGraph(){
LineChart chart = (LineChart) findViewById(R.id.chart);
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
chart.getAxisLeft().setAxisMaxValue(100);
chart.getXAxis().setAxisMaxValue(100);
//Creating list of entries
LineDataSet dataset = new LineDataSet(entries, "# of Calls");
// creating labels
ArrayList<String> labels = new ArrayList<String>();
for (int i = 0; i < 10 + numEntries; i++) {
labels.add(Integer.toString(i));
}
LineData data = new LineData(labels, dataset);
entries.add(new Entry(testActivity.nums, numEntries));
chart.animateXY(1000,1000);
chart.notifyDataSetChanged();
chart.invalidate();
chart.setData(data); // set the data and list of lables into chart
}
public void counterClicked(View view){
try {
EditText inputText = (EditText) findViewById(R.id.edit_text_val);
int localNums = Integer.parseInt(inputText.getText().toString());
if (counter < 3) {
nums += localNums;
counter++;
numEntries++;
Toast.makeText(this, "Total Entries" + entries.get(0),
Toast.LENGTH_SHORT).show();
reDrawGraph();
inputText.getText().clear();
}
if (counter == 3){
lifetimeNums++;
numEntries++;
Intent intent = new Intent(this, SelectionActivity.class);
startActivity(intent);
}
}catch (Exception e) {
Toast.makeText(this, "Please enter a value",
Toast.LENGTH_SHORT).show();
}`
I'm trying to figure out exactly how to implement Google Play Game services in my app. On the Google Play Developer Console I've linked the game the relevant app using the SHA1 key and I know how to add leaderboards and achievements on here. I have also installed the Google Play services and Google Repository to Android Studio and added the dependency into build.gradle (as explained here: http://developer.android.com/google/play-services/setup.html) but I wasn't sure how to do the last 2 steps on that page (creating a Proguard exception and ensuring devices have the Google Play services APK) and if they are necessary - the latter of which even the Google Play Games sample projects don't seem to do.
Moreover, I'm not sure what code I actually need to put in my project to enable leaderboards and achievements, since according to this guide: https://developers.google.com/games/services/android/achievements, I use this code:
Games.Achievements.unlock(mGoogleApiClient, "my_achievement_id");
to unlock an achievement, for example, but there are no instructions on how I set up mGoogleApiClient. I've looked at the sample projects but it's still not clear what I'm supposed to do. Am I meant to copy and paste all of the code into my project? Are there certain sections I'm supposed to copy and paste? Do I have to write my own code for signing in to Google Play Games?
You should use getApiClient() instead of mGoogleApiClient.
Assuming you have an activity with a layout containing four buttons:
Leaderboard button - To launch the leaderboards,
Achievement button - To launch achievements
Sign in and Sign out buttons
For leaderboard, we push scores for best minutes, best distance covered and an overall highscore.
And for achievements, we unlock four achievements - survivor, warrior, lord, pride based on certain conditions.
Here's how you'd go about it:
public class GMSActivity extends BaseGameActivity implements OnClickListener{
Button lead;
Button achv;
final int RC_RESOLVE = 5000, RC_UNUSED = 5001;
//your game score. so we can push to cloud
int hS = 0;
//flags for achievements
boolean survivor;
boolean tribalWarriror;
boolean akonfemLord;
boolean zuluPride;
LinearLayout signInBar;
LinearLayout signOutBar;
Resources r;
private float bestTimeInSeconds;
private int bestTimeInMinutes;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.gms_layout);
r = getResources();
lead = (Button)findViewById(R.id.leaderboards);
achv = (Button)findViewById(R.id.achievements);
hS = loadScores();
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
lead.setOnClickListener(this);
achv.setOnClickListener(this);
signInBar = (LinearLayout)findViewById(R.id.sign_in_bar);
signOutBar = (LinearLayout)findViewById(R.id.sign_out_bar);
checkForAchievements();
if (isSignedIn()) {
onSignInSucceeded();
}else{
onSignInFailed();
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == lead){
if (isSignedIn()) {
startActivityForResult(Games.Leaderboards.getAllLeaderboardsIntent(getApiClient()), RC_UNUSED);
} else {
showAlert(getString(R.string.leaderboards_not_available));
}
}else if(v ==achv){
if (isSignedIn()) {
startActivityForResult(Games.Achievements.getAchievementsIntent(getApiClient()), RC_UNUSED);
} else {
showAlert(getString(R.string.achievements_not_available));
}
}else if(v.getId() == R.id.sign_in_button){
beginUserInitiatedSignIn();
}else if(v.getId() == R.id.sign_out_button){
signOut();
hello.setText(getString(R.string.signed_out_greeting));
signInBar.setVisibility(View.VISIBLE);
signOutBar.setVisibility(View.GONE);
}
#Override
public void onSignInFailed() {
hello.setText(getString(R.string.signed_out_greeting));
signInBar.setVisibility(View.VISIBLE);
signOutBar.setVisibility(View.GONE);
}
#Override
public void onSignInSucceeded() {
signInBar.setVisibility(View.GONE);
signOutBar.setVisibility(View.VISIBLE);
// Set the greeting appropriately on main menu
Player p = Games.Players.getCurrentPlayer(getApiClient());
String displayName;
if (p == null) {
// Log.w(TAG, "mGamesClient.getCurrentPlayer() is NULL!");
displayName = "";
} else {
displayName = p.getDisplayName();
}
// hello.setText("Hello, " + displayName);
pushAccomplishments();
Toast.makeText(this, getString(R.string.your_progress_will_be_uploaded),
Toast.LENGTH_LONG).show();
}
//check for achievements and unlock the appropriate ones
void checkForAchievements() {
// Check if each condition is met; if so, unlock the corresponding
// achievement.
bestTimeInSeconds = loadGameBestTimeSec();
if(bestTimeInSeconds >= 900){ //15 minutes
survivor = true;
tribalWarriror = true;
}
}
void pushAccomplishments() {
if (survivor)
Games.Achievements.unlock(getApiClient(), getString(R.string.achievement_survivor));
if (tribalWarriror)
Games.Achievements.unlock(getApiClient(), getString(R.string.achievement_tribal_warrior));
if(bestTimeInSeconds >= 60){ //1 minute atleast
bestTimeInMinutes = (int)bestTimeInSeconds/60;
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_best_time_minutes), bestTimeInMinutes);
}
if(bestTimeInSeconds >= 10){ // 1 meter atleast
int bestDistance = (int)bestTimeInSeconds/10;
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_best_distance_meters), bestDistance);
}
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_top_score_points), hS);
}
#Override
//loading scores and achievements
private int loadScores() {
// TODO Auto-generated method stub
int score = 0;
try{
preferences = new SecurePreferences(getApplicationContext(),
"besiPreferences", "1234", true);
score = Integer.parseInt(preferences.getString("highScore"));
}catch(Exception e){}
return score;
}
private float loadGameBestTimeSec() {
float time = 0;
try{
preferences = new SecurePreferences(getApplicationContext(),
"besiPreferences", "1234", true);
time = Float.parseFloat(preferences.getString("gameTimeSec"));
}catch(Exception e){}
return time;
}
private int loadCalabashesCompleted() {
try{
preferences = new SecurePreferences(getApplicationContext(),
"makolaPref", "1234", true);
return Integer.parseInt(preferences.getString("bookCompleted")== null ? "0" : preferences.getString("bookCompleted"));
}catch(Exception e){
return 0;
}
}
private int loadLevelCompleted() {
try{
preferences = new SecurePreferences(getApplicationContext(),
"makolaPref", "1234", true);
return Integer.parseInt(preferences.getString("levelCompleted")== null ? "0" : preferences.getString("levelCompleted"));
}catch(Exception e){
return 0;
}
}
}