-2

1)I have the following code (originally clicked is false):

void configure_button(){
    // first check for permissions
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.INTERNET}
                    ,10);
        }
        return;
    }
    // this code won't execute IF permissions are not allowed, because in the line above there is return statement.
    b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //noinspection MissingPermission
            if (clicked){
                locationManager.removeUpdates(listener);
            }
            else {
                locationManager.requestLocationUpdates("gps", 5000, 0, listener);
            clicked=true;}
            distance=0;
            clicked=true;
            preloc=null;
            time1=c.get(Calendar.SECOND);
        }
    });
}

Android studio shows this error:

Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException.

However, if locationManager.requestLocationUpdates("gps", 5000, 0, listener); is outside and before the if, the code works fine. What is the problem?

2) How do I notify android that it is time to upgrade an SQLite Database? In other words, when does Android call onUpgrade?

3) When coordinates are found, they have many fractional points, but when they are stored and retrived from and SQLite database (stored as two floats), they only have 4 . For example, 41.13507153... will be stored as 41.1350. Is that normal? Is this enough to get an accurate location?

MikeT
  • 51,415
  • 16
  • 49
  • 68
Charor
  • 94
  • 1
  • 12

1 Answers1

-1

1) I believe that you can just redo the check in the else clause i.e. it's saying that it can't be sure that the checking code will always be undertaken because you are setting a listener which runs independently of the code that sets the listener.

I'd suggest having a read of Android check permission for LocationManager.

2) How do I notify android that it is time to upgrade an SQLite Database? In other words, when does Android call onUpgrade?

onUpgrade is called when the version number is increased, there is also an onDowngrade which is called when the version number is reduced.

In short YOU specify when by changing the version number passed, as the 4th parameter, to the SQLiteOpenHelper's super.

Example 1 Change DBVERSION to be 2 for onUpgrade to be called.

public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;

public class DBHelper extends SQLiteOpenHelper {


    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    .....
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    ''''
    }

Example 2 Version passed via the helper

public class DBHelper extends SQLiteOpenHelper {


        public DBHelper(Context context, String dbname, int version) {
            super(context, dbname, null, version);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
        .....
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        ''''
        }

Code in activity; changing DBVERSION will pass the new version through to the helper and call onUpgrade.

public static final String DBNAME = "mydb";
public static final String DBVERSION = 1;

DBHleper myhelper = new DBHelper(this,DBNAME,DBVERSION);

One thing to be wary of is that many tutorials have code like :-

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TblLogin);
        onCreate(db);
    }

Which would effectively destroy any existing data. So if you are upgrading a database and you don't want to lose the data, you have to include code that caters for this as the above code will only change the structure.

3) Is that normal?

According to the SQLite documentation, as per link:-

REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.

A column will be REAL, when REAL, DOUBLE, DOUBLE PRECISION or FLOAT is specified as the column type (actually the following applies If the declared type for a column contains any of the strings "REAL", "FLOA", or "DOUB" then the column has REAL affinity. BUT this is the 4th rule; others rules such as rule 1 for INT would have INTREAL be INTEGER).

This might be of interest Datatypes In SQLite Version 3 , which is the basis of the above.

What you might be doing is getting the data from the cursor via cursor.getString(columnindex), which I believe reduces the precision. To get a higher precision then use getDouble(columnindex);

e.g. I did (hastily put together):-

MyDBHelper mydbhelper = new MyDBHelper(this);
    mydbhelper.insertRow(1.3);
    mydbhelper.insertRow(1);
    mydbhelper.insertRow(5.674389123459834);

    Cursor getfloats = mydbhelper.getAllMyFloats();
    Log.d("TESTFLOAT","Rows returned from getALlFloats = " + getfloats.getCount());
    while (getfloats.moveToNext()) {
        Log.d("TESTFLOAT","Via getString = " + getfloats.getString(getfloats.getColumnIndex(mydbhelper.MYFLOATCOL)));
        Log.d("TESTFLOAT","Via getFloat = " + Float.toHexString(
                getfloats.getFloat(
                        getfloats.getColumnIndex(
                                mydbhelper.MYFLOATCOL
                        )
                )
        ));
        Log.d("TESTFLOAT","Via getDouble = " +Double.toString(
                getfloats.getDouble(
                        getfloats.getColumnIndex(
                                mydbhelper.MYFLOATCOL
                        )

                )));
    }
    getfloats.close();

MyDBHelper being :-

public class MyDBHelper extends SQLiteOpenHelper {

    public static final String DBNname = "mydb";
    public static final int DBVersion = 1;
    public static final String TESTFLOATTABLE = "testfloat";
    public static final String STDIDCOL = "_id INTEGER PRIMARYKEY";
    public static final String MYFLOATCOL = "myfloat";
    public static final String MYFLOATTYPE = " FLOAT DEFAULT 0.0";

    public MyDBHelper(Context context) {
        super(context,DBNname,null,DBVersion);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " +
                TESTFLOATTABLE +
                "(" +
                STDIDCOL +
                "," +
                MYFLOATCOL +
                MYFLOATTYPE +
                ")");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldeversion, int newversion) {

    }

    public long insertRow(double myfloatvalue) {
        long rv;
        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(MYFLOATCOL,myfloatvalue);
        rv = db.insert(TESTFLOATTABLE,null,cv);
        return rv;
    }

    public Cursor getAllMyFloats() {
        Cursor rv;
        SQLiteDatabase db = getReadableDatabase();
        rv = db.query(TESTFLOATTABLE,null,null,null,null,null,null);
        return rv;
    }
}

The results from a first run (subsequent runs will add another set of rows and so on) :-

06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Rows returned from getALlFloats = 3
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getString = 1.3
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getFloat = 0x1.4cccccp0
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getDouble = 1.3
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getString = 1
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getFloat = 0x1.0p0
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getDouble = 1.0
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getString = 5.67439
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getFloat = 0x1.6b293p2
06-05 10:49:35.279 21951-21951/mjt.testvcsuse D/TESTFLOAT: Via getDouble = 5.674389123459834

So looking at the last 3 rows, getString, gets to 5dp, whilst getDouble gets to 15dp here (not sure of the max precision, a quick look suggests 15-17).

MikeT
  • 51,415
  • 16
  • 49
  • 68
  • about 2): so, in my activity, when I start the database, i pass the version history, which i then pass to super, and if the new value is greater than the previous value, the onUpgrade will be called? – Charor Jun 04 '17 at 10:32
  • Yes, although I'd say when you want to upgrade the database you decide to introduce a new version and you pass this through to super (you could for example have the super call as `super(context,DBNAME,DBVERSION);` and then just incrementing DBVERSION would result in `onUpgrade` being called). I'll add some examples to the answer. – MikeT Jun 04 '17 at 20:19
  • thank you, Ill try the permimssion check, and yes the cursor does ask for a String.The onUpgrade works fine – Charor Jun 05 '17 at 07:18