gpt4 book ai didi

java - getLastLocation 使用反射与 GoogleApiClient 和 LocationServices

转载 作者:行者123 更新时间:2023-11-30 02:01:02 26 4
gpt4 key购买 nike

我正在开发一个 Android 库,我需要删除由使用我的库的开发人员添加的播放服务依赖项。我需要用户位置最后一个位置,所以我需要使用反射,因为位置库不会直接包含在我的库中。

但是如何通过反射从构建器创建 googleApiClient 呢?

最佳答案

深入研究反射和 Play 服务会生成以下脚本。它包含用于获取 AdvertisingId 和位置的代码。

Gist also available .

private void getLocation(Context context) {
Log.d(LOG_TAG, "getLocation");

if (context.getPackageManager().checkPermission(
Manifest.permission.ACCESS_FINE_LOCATION, context.getPackageName()) == PackageManager.PERMISSION_GRANTED ||
context.getPackageManager().checkPermission(
Manifest.permission.ACCESS_COARSE_LOCATION, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {

try {
Class<?> apiClientBuilderClass = Class.forName("com.google.android.gms.common.api.GoogleApiClient$Builder");
Class<?> connectionCallbackClass = Class.forName("com.google.android.gms.common.api.GoogleApiClient$ConnectionCallbacks");
Class<?> connectionFailedCallbackClass = Class.forName("com.google.android.gms.common.api.GoogleApiClient$OnConnectionFailedListener");
Class<?> locationServicesClass = Class.forName("com.google.android.gms.location.LocationServices");

Constructor<?> constructorApiBuilder = apiClientBuilderClass.getConstructor(Context.class);
Object objectApiBuilder = constructorApiBuilder.newInstance(mContext);

// Create intance of listener ConnectionCallbacks
Class<?>[] connectionClassArray = new Class<?>[1];
connectionClassArray[0] = connectionCallbackClass;
sGoogleApiClientListener = Proxy.newProxyInstance(
connectionCallbackClass.getClassLoader(), connectionClassArray, new GoogleApiClientListener());

Method connectionMethodObject = apiClientBuilderClass.getMethod("addConnectionCallbacks", connectionCallbackClass);
connectionMethodObject.invoke(objectApiBuilder, sGoogleApiClientListener);

// Create instance of OnConnectionFailedListener listener

Class<?>[] connectionFailedClassArray = new Class<?>[1];
connectionFailedClassArray[0] = connectionFailedCallbackClass;
sGoogleApiClientFailedListener = Proxy.newProxyInstance(
connectionFailedCallbackClass.getClassLoader(), connectionFailedClassArray, new GoogleApiClientFailedListener());

Method connectionFailedMethodObject = apiClientBuilderClass.getMethod("addOnConnectionFailedListener", connectionFailedCallbackClass);
connectionFailedMethodObject.invoke(objectApiBuilder, sGoogleApiClientFailedListener);

// Add Api
Method addApiMethod = apiClientBuilderClass.getMethod("addApi", Class.forName("com.google.android.gms.common.api.Api"));
addApiMethod.invoke(objectApiBuilder, locationServicesClass.getField("API").get(null));

// Build
Method buildMethod = apiClientBuilderClass.getMethod("build");
sGoogleApiClient = buildMethod.invoke(objectApiBuilder);

// Connect
for (Method method : sGoogleApiClient.getClass().getMethods()) {
if (!"connect".equals(method.getName())) {
continue;
}

method.invoke(sGoogleApiClient);
break;
}

} catch (Exception e) {
// Location is not essential, so it's not an error
Log.v(LOG_TAG, "Exception on getLocation " + Log.getStackTraceString(e));
}

} else {
sLocation = "";
}
}

// GoogleApiClient for Locationsucceded
public void onConnected() {
Location lastLocation = null;
try {
// FusedLocationApi is a field of LocationServices, getting it.
Class<?> locationServicesClass = Class.forName("com.google.android.gms.location.LocationServices");
Class<?> locationProviderClass = Class.forName("com.google.android.gms.location.FusedLocationProviderApi");
for (Method method : locationProviderClass.getMethods()) {
if (!"getLastLocation".equals(method.getName())) {
continue;
}

Object object = locationServicesClass.getField("FusedLocationApi").get(null);
lastLocation = (Location) method.invoke(object, sGoogleApiClient);
break;
}

} catch (Exception e) {
// Location is not essential, so it's not an error
Log.v(LOG_TAG, "Exception on invoke onConnected for getLastLocation" + Log.getStackTraceString(e));
}

// Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(sGoogleApiClient);

if (lastLocation != null) {
sLocation = lastLocation.getLatitude() + "," + lastLocation.getLongitude();
Log.d(LOG_TAG, "Location received : " + sLocation);
} else {
sLocation = "";
}

newResourcesAvailable();
unregisterConnectionCallbacks();
}

// GoogleApiClient for Location failed somewhere

public void onConnectionSuspended() {
sLocation = "";

newResourcesAvailable();
unregisterConnectionCallbacks();
}

// GoogleApiClient for Location failed somewhere
public void onConnectionFailed() {
sLocation = "";
newResourcesAvailable();
unregisterConnectionCallbacks();
}

private void unregisterConnectionCallbacks(){

for (Method method : sGoogleApiClient.getClass().getMethods()) {
if (!"unregisterConnectionCallbacks".equals(method.getName())) {
continue;
}
try {
method.invoke(sGoogleApiClient, sGoogleApiClientListener);
} catch (Exception ignored) {
// Exception always occur here but cannot make it work
}
break;
}

for (Method method : sGoogleApiClient.getClass().getMethods()) {
if (!"unregisterConnectionFailedListener".equals(method.getName())) {
continue;
}
try {
method.invoke(sGoogleApiClient, sGoogleApiClientFailedListener);
} catch (Exception ignored) {
// Exception always occur here but cannot make it work
}
break;
}
}

protected class RetrieveAdvertisingId extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
String id = "";

try {
Object AdvertisingInfoObject = getAdvertisingInfoObject(mContext);
id = (String) invokeInstanceMethod(AdvertisingInfoObject, "getId", null);
} catch (Exception e) {
// Catch reflection exception and GooglePlayServicesNotAvailableException |
// GooglePlayServicesRepairableException

Log.e(LOG_TAG, "Exception while getting AdvertisingId", e);
}

return id;
}

@Override
protected void onPostExecute(String advertisingId) {
super.onPostExecute(advertisingId);


if (advertisingId != null && !advertisingId.isEmpty()) {
Log.i(LOG_TAG, "Advertising ID retrieved: " + advertisingId);

sAdvertisingId = advertisingId;
} else {
Log.e(LOG_TAG, "AdversitingId is not available");
sAdvertisingId = "";
}

AsynchronousParameterManager.this.newResourcesAvailable();
}
}

/**
* Returns the AdvertisingIdInfo object
*
* @param context the android context
* @return the advertising id information object
* @throws Exception
*/
private Object getAdvertisingInfoObject(Context context) throws Exception {
return invokeStaticMethod(
"com.google.android.gms.ads.identifier.AdvertisingIdClient",
"getAdvertisingIdInfo",
new Class[]{Context.class},
context
);
}

/**
* Invokes a static method within a class
* if it can be found on the classpath.
*
* @param className The full defined classname
* @param methodName The name of the method to invoke
* @param cArgs The args that the method can take
* @param args The args to pass to the method on invocation
* @return the result of the method invoke
* @throws Exception
*/
private Object invokeStaticMethod(String className, String methodName,
Class[] cArgs, Object... args) throws Exception {
Class classObject = Class.forName(className);
return invokeMethod(classObject, methodName, null, cArgs, args);
}

/**
* Invokes a method on a static instance
* within a class by reflection.
*
* @param instance The instance to invoke a method on
* @param methodName The name of the method to invoke
* @param cArgs The args that the method can take
* @param args The args to pass to the method on invocation
* @return the result of the method invoke
* @throws Exception
*/
private Object invokeInstanceMethod(Object instance, String methodName,
Class[] cArgs, Object... args) throws Exception {
Class classObject = instance.getClass();
return invokeMethod(classObject, methodName, instance, cArgs, args);
}

/**
* Invokes methods of a class via reflection
*
* @param classObject The class to attempt invocation on
* @param methodName The name of the method to invoke
* @param instance The object instance to invoke on
* @param cArgs The args that the method can take
* @param args The args to pass to the method on invocation
* @return the result of the method invoke
* @throws Exception
*/
private Object invokeMethod(Class classObject, String methodName, Object instance,
Class[] cArgs, Object... args) throws Exception {
Method methodObject = classObject.getMethod(methodName, cArgs);
return methodObject.invoke(instance, args);
}

private class GoogleApiClientListener implements InvocationHandler {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (args != null) {
if (method.getName().equals("onConnected")) {
AsynchronousParameterManager.this.onConnected();
} else if (method.getName().equals("onConnectionSuspended") ) {
AsynchronousParameterManager.this.onConnectionSuspended();
}
} else {
return 0;
}
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return null;
}
}


private class GoogleApiClientFailedListener implements InvocationHandler {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
if (method.getName().equals("onConnectionFailed")) {
AsynchronousParameterManager.this.onConnectionFailed();
}

return 0;

} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
}
}

关于java - getLastLocation 使用反射与 GoogleApiClient 和 LocationServices,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31471143/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com