java - 无论应用程序处于什么状态,都获取设备的位置始终从我的公司应用程序中检测位置

标签 java android flutter geolocation

我想使用公司应用程序获取公司设备的位置。

当应用程序位于前台时,我成功地定位了设备,但当应用程序位于后台或被杀死时,我似乎无法正常工作。

当应用程序关闭或在后台时,我尝试使用推送通知来启动服务或广播接收器,但没有任何效果。

有没有办法无论应用程序处于什么状态都可以获取设备的位置?

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.c7lab.fotodinamico">

    <!--
     io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here.
    -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="Corporate Application">
        <receiver android:name=".MyLocationService"></receiver>


        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:windowSoftInputMode="adjustResize">

            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>


        <service
            android:name="com.example.crm_agenti.MyFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
    </application>

</manifest>

MyLocationService.class

package com.c7lab.fotodinamico;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.util.Log;

import com.google.android.gms.location.LocationResult;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import static android.content.Context.MODE_PRIVATE;


public class MyLocationService extends BroadcastReceiver {

    public static final String ACTION_PROCESS_UPDATE = "com.c7lab.fotodinamico.UPDATE_LOCATION";
    private static final String TAG = "MyLocationService";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "MYSERVICE WORK?");
        SharedPreferences prefs = context.getSharedPreferences("FlutterSharedPreferences", MODE_PRIVATE);
        String shared = prefs.getString("flutter.jsonData", null);
        JsonObject ed = new JsonObject();
        Gson g = new Gson();
        if(shared != null) {
            ed = new JsonParser().parse(shared).getAsJsonObject();
        }

        String usr = "no-usr";
        if(ed.get("usr") != null) {
            usr = ed.get("usr").getAsString();
        }
        if(intent != null) {
            final String action = intent.getAction();
            if(ACTION_PROCESS_UPDATE.equals(action)) {
                LocationResult result = LocationResult.extractResult(intent);
                if(result != null) {
                    Location location = result.getLastLocation();
                    double latitude = location.getLatitude();
                    double longitude = location.getLongitude();

                    String location_string = new StringBuilder(""+latitude).append(" - ").append(longitude).toString();
                    Log.v(TAG,location_string);
                }
            }
        }
    }
}

MainActivity.class

package com.c7lab.fotodinamico;

import android.Manifest;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.WindowManager.LayoutParams;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import com.karumi.dexter.Dexter;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.single.PermissionListener;

import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;


public class MainActivity extends FlutterActivity {
  private static final String TAG = "MainActivity";
  private Handler mainHandler = new Handler();

  static MainActivity instance;
  LocationRequest locationRequest;
  FusedLocationProviderClient fusedLocationProviderClient;

  public static MainActivity getInstance() {
    return instance;
  }


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
    //scheduleJob();
    getWindow().addFlags(LayoutParams.FLAG_SECURE);


    Dexter.withActivity(this)
            .withPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
            .withListener(new PermissionListener() {
              @Override
              public void onPermissionGranted(PermissionGrantedResponse response) {
                  updateLocation();
              }

              @Override
              public void onPermissionDenied(PermissionDeniedResponse response) {
                  Toast.makeText(MainActivity.this, "Accetta permessi posizione.", Toast.LENGTH_SHORT).show();

              }

              @Override
              public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {

              }
            }).check();
  }

  @Override
  protected void onStop() {
    // call the superclass method first
    super.onStop();

  }

    private void updateLocation() {
        buildLocationRequest();
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        fusedLocationProviderClient.requestLocationUpdates(locationRequest, getPendingIntent());
    }

    private PendingIntent getPendingIntent() {
        Intent intent = new Intent(this, com.c7lab.fotodinamico.MyLocationService.class);
        intent.setAction(com.c7lab.fotodinamico.MyLocationService.ACTION_PROCESS_UPDATE);

        return PendingIntent.getBroadcast(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

    }

    private void buildLocationRequest() {
        locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(5000);
        locationRequest.setFastestInterval(3000);
        locationRequest.setSmallestDisplacement(10f);
    }


}

我已经尝试过此网站上编写的多种解决方案!

最佳答案

问题很多。

1) 不要使用 getLastLocation。仅当设备已经知道位置时,这才有效。相反,使用 requestSingleUpdate 来实际打开位置硬件。这需要您使用真正的服务,因为 BroadcastReceiver 会很快被终止。不过 BR 可以启动该服务。

2)您需要前台服务,而不是后台服务。

3) 在现代 Android 中,用户可以选择仅在应用程序打开时授予位置并阻止所有后台访问。设备策略所有者可能可以覆盖此设置,但不确定。但如果不能,你就完蛋了。

关于java - 无论应用程序处于什么状态,都获取设备的位置始终从我的公司应用程序中检测位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59738745/

相关文章:

java - ElasticSearch Java 客户端查询嵌套对象

java - 如何使用 JUnit 与 Spring 和 Hibernate 来模拟事务的结束以隔离 LazyInitializationException?

java - 使用 JDBC 将自己制作的 Windows 凭据传递到 SQL Server

api - 为什么会收到错误消息:Android Gradle插件仅支持Kotlin Gradle插件1.3.10及更高版本

java - Log4j 不附加文件扩展名

android - 使用 Application 类保存当前配置

java - 如何使用 layout_weight 获取 LinearLayout 的像素高度

安卓。 Mockito 使用真实对象而不是模拟对象

flutter - 禁用桌面支持 Flutter

flutter - 在 VSCode 中调试当前打开的 Flutter 文件