0

Please help, I can find the distance of one beacon but I can't populate a listview with other beacons in the region. I've tested the listview by just using a string array, populates fine. Everything else works but I'm at a total loss for this last part, close to the edge here...

Here's my code for the main activity`import android.app.Activity;

import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.widget.*;
import org.altbeacon.beacon.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

public class MainActivity extends Activity implements BeaconConsumer{



    private BeaconManager beaconManager;
    int distance;
    Identifier minorID;
    double distanceLong;
    private Handler mHandler;
    private int i;
    public TextView distanceText;
    public TextView distanceName1;
    public ImageView distanceImage;
    public String name1;
    public boolean exitRegion = false;
    public String minorString;
    List<String> beaconList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = getIntent();

         name1 = intent.getStringExtra("beacon1");


        beaconManager = BeaconManager.getInstanceForApplication(this);

        beaconManager.getBeaconParsers().add(new BeaconParser()
                .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));

        beaconManager.bind(this);


        distanceText = (TextView) findViewById(R.id.distanceText);
        distanceText.setText("No beacons found yet, please wait");






            distanceName1 = (TextView) findViewById(R.id.name1);
            distanceName1.getText();
            distanceName1.setText("How far away is "+name1+"?");



        distanceText = (TextView) findViewById(R.id.distanceText);
        distanceText.getText();
        distanceText.setText("Distance: " + distance+ " metres");
        distanceImage = (ImageView) findViewById(R.id.distanceImage);
        //alertDialogue();

        i = 0;
        mHandler = new Handler() {
            @Override
            public void close() {

            }

            @Override
            public void flush() {

            }

            @Override
            public void publish(LogRecord record) {

            }
        };




        beaconList = new ArrayList<String>();
        ListAdapter beaconAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, beaconList);
        ListView beaconListView = (ListView) findViewById(R.id.beaconListView);
        beaconListView.setAdapter(beaconAdapter);


        distanceText.post(mUpdate);
        distanceImage.post(mUpdate);


    }





    private Runnable mUpdate = new Runnable() {
        public void run() {



            distanceText.setText("Distance: " + distance+ " ms");
            imageDistance(distance);
            alertDialogue(distance);
            i++;
            distanceText.postDelayed(this, 10000);


        }
    };


    @Override
    protected void onDestroy() {
        super.onDestroy();
        beaconManager.unbind(this);
    }

    @Override
    public void onBeaconServiceConnect() {
        final Region region = new Region("myBeacons", Identifier.parse("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);

        beaconManager.setMonitorNotifier(new MonitorNotifier() {
            @Override
            public void didEnterRegion(Region region) {
                try {
                    Log.d(TAG, "didEnterRegion");
                    exitRegion=false;
                    beaconManager.startRangingBeaconsInRegion(region);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void didExitRegion(Region region) {
                try {
                    Log.d(TAG, "didExitRegion");
                    exitRegion = true;
                    beaconManager.stopRangingBeaconsInRegion(region);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void didDetermineStateForRegion(int i, Region region) {

            }
        });

        beaconManager.setRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                for(Beacon oneBeacon : beacons) {


                    distanceLong = oneBeacon.getDistance();
                    distance = (int) distanceLong;
                    minorID = oneBeacon.getId3();
                    minorString = minorID.toString();
                    String distanceString = String.valueOf("Distance of " + minorID +" beacon: "+ (int) distanceLong+ " metres");
                    beaconList.add(distanceString);

                    Beacon.setHardwareEqualityEnforced(true);

                }


            }
        });

        try {
            beaconManager.startMonitoringBeaconsInRegion(region);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

`

My layout code is here, as I said the UI mostly works already but maybe I've missed something with the listview...

 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"

            android:layout_height="match_parent">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
              android:orientation="vertical"

    tools:context="${relativePackage}.${activityClass}">



    <TextView
                android:layout_width="wrap_content"
                android:layout_height="60dp"
                android:textColor="@color/material_blue_grey_800"
                android:textSize="25sp"
                android:id="@+id/name1"
                android:layout_gravity="center_horizontal"
                android:layout_margin="10dp"

    />


        <TextView android:layout_width="wrap_content"
                  android:layout_height="60dp"
                  android:id="@+id/distanceText"
                  android:textColor="@color/material_blue_grey_800"
                  android:textSize="25sp"
                  android:layout_margin="10dp"
                  android:layout_gravity="center_horizontal"
                  android:layout_below="@+id/name1"

    />
        <ImageView android:layout_width="150dp"
                       android:layout_height="150dp"
                       android:id="@+id/distanceImage"
                       android:layout_margin="10dp"
                       android:layout_below="@+id/distanceText"
                       android:layout_gravity="center_horizontal"
        />

        <ListView android:layout_width="match_parent"
                  android:layout_height="match_parent"
                    android:id="@+id/beaconListView"
                  android:textColor="@color/material_blue_grey_800"
                  android:textSize="25sp"
        ></ListView>


</LinearLayout></ScrollView>

1 Answers1

0

A few tips:

  • You don't need the separate beaconList, only the beaconAdapter. But you do need to move the declaration of the beaconAdapter to be a class level variable like this:

    ...
    public String minorString;
    private ListAdapter beaconAdapter;
    ...
    
  • Then you can initialize it the same place you do now, just remove the declaration part. You can also remove the reference to beaconList, which is unneeded:

    beaconAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
    
  • In the didRangeBeaconsInRegion callback, you then update the entries in the beaconAdapter. Like this:

    public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
        beaconAdapter.clear();
        for(Beacon oneBeacon : beacons) {
            distanceLong = oneBeacon.getDistance();
            distance = (int) distanceLong;
            minorID = oneBeacon.getId3();
            minorString = minorID.toString();
            String distanceString = String.valueOf("Distance of " + minorID +" beacon: "+ (int) distanceLong+ " metres");
            beaconAdapter.add(distanceString);
            Beacon.setHardwareEqualityEnforced(true);
        }
        beaconAdapter.notifyDataSetChanged()            
    }
    

Note that in the code above, notifyDataSetChanged() is called as @niels-masdorp correctly says to do in his answer.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • Isn't this pretty much what I answered minus the optional `List` (which quickly becomes cumbersome when you want to access the data from anything that isn't view related)? – Niels Masdorp Apr 10 '16 at 21:35
  • Hi thank you for the response - basically, when I attempt to update the beaconAdapter in the didRangeBeaconsInRegion method, it doesn't recognise the inbuilt methods .clear(), .add() or .notifyDataSetChanged() but those methods do work for beaconList. Maybe I'm missing an import or something? I've followed your code very closely, cutting and pasting above – Rose Kane Quinn Apr 10 '16 at 21:59
  • I've also removed any reference to beaconList as well but it's not working – Rose Kane Quinn Apr 10 '16 at 22:01
  • Make sure `beaconAdapter` is declared as a `android.widget.ListAdapter`. – davidgyoung Apr 11 '16 at 02:44
  • Yeah I did that, still not working, I have no idea why the adapter isn't showing those methods. – Rose Kane Quinn Apr 11 '16 at 07:06
  • Ok, ran it after reimporting everything but the app crashed and here is the error E/AndroidRuntime﹕ FATAL EXCEPTION: IntentService[BeaconIntentProcessor] Process: com.myapplication2.app, PID: 20096 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6875) at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1019) Any ideas what it might be?? – Rose Kane Quinn Apr 11 '16 at 17:38
  • Wrap the line of code giving you that error in runOnUIThread() as shown here http://stackoverflow.com/questions/11140285/how-to-use-runonuithread – davidgyoung Apr 11 '16 at 18:05
  • I've taken a different approach by adding the distanceString to an array int arraySize = myArray.size();
 for(int i = 0; i < arraySize; i++) {Text.append(myArray.get(i));
 descriptionText.append("\n");
 i++;
 } It's fairly inelegant but it's working so far for me despite it being quite slow. Thanks for your help – Rose Kane Quinn Apr 11 '16 at 20:12