【问题标题】:Gluon Mobile - Android: Ask for location permission when accessing locationGluon Mobile - Android:访问位置时请求位置权限
【发布时间】:2018-05-18 22:58:36
【问题描述】:

我们在基于 Gluon 的应用程序的地图上显示用户位置。只要用户打开了“位置”,它就可以正常工作(我们仍然需要调整一些较小的东西)。但是,当它未打开时,应用程序会崩溃。 “AndroidManifest.xml”包含所需的权限行。我们尝试了几个 Android 版本,从 5.1.1 到 6.0.1 到 7.1.1,以检查它是否与 Android 版本本身有关。

另一方面,当我们在 iPhone 上使用我们的应用程序时,系统会处理此请求并提示用户允许访问该位置。即使用户拒绝,应用程序也不会崩溃。

有没有办法为 Android 实现相同的行为?

编辑以便更好地理解: jfxmobile 版本 1.3.10

AndroidManifest.xml:

    <?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ch" android:versionCode="1"
          android:versionName="0.9.6 Beta">
    <supports-screens android:xlargeScreens="true"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="23"/>

    <application android:label="BodenDok" android:name="android.support.multidex.MultiDexApplication"
                 android:icon="@mipmap/ic_launcher"
                 android:largeHeap="true">
        <activity android:name="javafxports.android.FXActivity" android:label="BodenDok"
                  android:screenOrientation="portrait"
                  android:configChanges="orientation|screenSize">
            <meta-data android:name="main.class" android:value="ch.BodenDok"/>
            <meta-data android:name="debug.port" android:value="0"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Permission request, Android 23+ -->
        <activity android:name="com.gluonhq.impl.charm.down.plugins.android.PermissionRequestActivity" />

        <activity android:name="com.gluonhq.impl.charm.down.plugins.android.NotificationActivity"
                  android:parentActivityName="javafxports.android.FXActivity">
            <meta-data android:name="android.support.PARENT_ACTIVITY"
                       android:value="javafxports.android.FXActivity"/>
        </activity>
        <receiver android:name="com.gluonhq.impl.charm.down.plugins.android.AlarmReceiver" />
    </application>
</manifest>

build.gradle:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.3.10'
    }
}

apply plugin: 'org.javafxports.jfxmobile'
apply plugin: 'checkstyle'

ext.checkstyleVersion    = '8.3'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'ch.BodenDok'

dependencies {
    compile 'com.gluonhq:charm:5.0.0'
    // https://mvnrepository.com/artifact/org.controlsfx/controlsfx
    compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.14'

    testCompile 'junit:junit:4.12'
}

jfxmobile {
    downConfig {
        version = '3.8.0'
        // Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
        plugins 'compass', 'display', 'lifecycle', 'local-notifications', 'magnetometer', 'pictures', 'position', 'runtime-args', 'settings', 'share', 'statusbar', 'storage'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
        compileSdkVersion = 25
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.gluonhq.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*'
        ]
    }
}

checkstyle {
    toolVersion ="${checkstyleVersion}"
    configFile = project(':').file('config/checkstyle/checkstyle.xml')
    configProperties = [ "suppressionFile" : project(':').file('config/checkstyle/suppressions.xml')]
}

编辑:好像这条线

 <activity android:name="com.gluonhq.impl.charm.down.plugins.android.PermissionRequestActivity" />

José Pereda 建议不在应用程序标签内。现在 Android 7.1.2 直接显示位置屏幕,Android 5.1.1 仍然崩溃应用程序。有什么方法可以询问正在运行哪个 Android 版本?例如。 “Platform.Android.version”或“MobileApplication.Android.version”,以便我们可以相应地捕获错误?

【问题讨论】:

  • 我不了解 Gluon,但是对于 android,您是否检查了构建版本是否
  • 是的,发布您的清单、项目的 build.gradle 和 jfxmobile 版本
  • 感谢您的回答;我在上面的原始帖子中添加了代码 sn-ps。据我了解,Android 5.1.1 到 6.0.1 的权限系统发生了很大的变化。无论如何,我们希望支持 Android 5.1.1(版本 21)。这两种版本都可以实现吗?

标签: android gluon-mobile runtime-permissions


【解决方案1】:

好吧,诀窍是在这里使用显式广播接收器。在此代码中,当 GPS 未连接或关闭时,将显示一个对话框,提醒您没有 Gps 连接,单击“重试”将带您进入设置页面,您可以在其中打开 GPS。

广播接收器的显式方法

 private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
      if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
          checkGPS();
      }

  }  };

用于向用户询问权限(运行时权限)

  public boolean checkLocationpermission() {
  if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
      if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
          ActivityCompat.requestPermissions(this, new String[] {
              Manifest.permission.ACCESS_FINE_LOCATION
          }, 1001);
      } else {
          ActivityCompat.requestPermissions(this, new String[] {
              Manifest.permission.ACCESS_FINE_LOCATION
          }, 1003);

      }
      return false;
  } else
      return true;  }

CheckGps 方法

 public void checkGPS() {
 builder = new AlertDialog.Builder(this);
 builder.setTitle("NO GPS");
 if (isGPSready()) {
     System.out.println("GPs Connected");
 } else {
     builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
         @Override
         public void onClick(DialogInterface dialogInterface, int i) {
             if (!isGPSready()) {
                 startActivityForResult(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), 1001);

                 builder.show();
             } else if (isGPSready()) {
                 System.out.println("the connection is succsful");

             }
         }
     }).setNegativeButton("No", new DialogInterface.OnClickListener() {
         @Override
         public void onClick(DialogInterface dialogInterface, int i) {
             finish();
         }
     });
     builder.show();
 } }

onActivityResult 方法

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == 1001) {
       if (mLocationManager == null) {
           mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
       } else if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
           checkGPS();
       }

   }
   super.onActivityResult(requestCode, resultCode, data);   }

这是完整的代码

公共类 MainActivity 扩展 AppCompatActivity {

AlertDialog.Builder builder;
LocationManager mLocationManager;

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
            //isGPSready();
            checkGPS();
        }

    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    checkLocationpermission();
    checkGPS();
    registerReceiver(broadcastReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
}
public boolean isGPSready() {
    mLocationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
    return mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}

public void checkGPS() {
    builder = new AlertDialog.Builder(this);
    builder.setTitle("NO GPS");
    builder.setMessage("Click on Retry to get connected to GPS");
    if (isGPSready()) {
        System.out.println("GPs Connected");
    } else {
        builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                if (!isGPSready()) {
                    startActivityForResult(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), 1001);
                    builder.show();
                } else if (isGPSready()) {
                    System.out.println("the connection is succsful");

                }
            }
        }).setNegativeButton("No", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                finish();
            }
        });
        builder.show();
    }

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1001) {
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        } else if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            checkGPS();
        }

    }
    super.onActivityResult(requestCode, resultCode, data);

}

public boolean checkLocationpermission() {
    if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
            ActivityCompat.requestPermissions(this, new String[] {
                Manifest.permission.ACCESS_FINE_LOCATION
            }, 1001);
        } else {
            ActivityCompat.requestPermissions(this, new String[] {
                Manifest.permission.ACCESS_FINE_LOCATION
            }, 1003);
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        }
        return false;
    } else
        return true;
}}

【讨论】:

  • 我认为你不需要自己实现它......因为它已经存在了。如果您检查 Javadoc 以获取 Down 3.8.0,则包含 PermissionRequest 活动,用于 Position service 或其他活动。另请参阅此post 中的Runtime permissions request on Android
  • karan:感谢您的解释 - 由于我们对应用程序编程比较陌生,非常感谢您的回答! :) @JoséPereda:我们发现,我们已经有运行时权限请求 - 但它在 -tag 之外。
猜你喜欢
  • 1970-01-01
  • 2018-12-21
  • 2016-06-02
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
相关资源
最近更新 更多