mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2024-12-24 11:45:50 +01:00
Location API mainly done
This commit is contained in:
parent
6af3c0b700
commit
a5be10d11b
@ -8,8 +8,8 @@ import com.google.android.gms.common.api.PendingResult;
|
||||
import org.microg.gms.Constants;
|
||||
|
||||
public interface FusedLocationProviderApi {
|
||||
String KEY_LOCATION_CHANGED = "com.google.android.location.LOCATION";
|
||||
String KEY_MOCK_LOCATION = Constants.KEY_MOCK_LOCATION;
|
||||
public static final String KEY_LOCATION_CHANGED = "com.google.android.location.LOCATION";
|
||||
public static final String KEY_MOCK_LOCATION = Constants.KEY_MOCK_LOCATION;
|
||||
|
||||
public Location getLastLocation(GoogleApiClient client);
|
||||
|
||||
|
@ -1,78 +1,63 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.google.android.gms.common.GooglePlayServicesClient;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.common.api.PendingResult;
|
||||
|
||||
import org.microg.gms.common.ForwardConnectionCallbacks;
|
||||
import org.microg.gms.common.ForwardConnectionFailedListener;
|
||||
import org.microg.gms.common.api.AbstractPlayServicesClient;
|
||||
import org.microg.gms.common.api.GoogleApiClientImpl;
|
||||
import org.microg.gms.location.LocationClientImpl;
|
||||
|
||||
@Deprecated
|
||||
public class LocationClient implements GooglePlayServicesClient {
|
||||
private GoogleApiClient googleApiClient;
|
||||
public class LocationClient extends AbstractPlayServicesClient {
|
||||
public static final String KEY_LOCATION_CHANGED = "com.google.android.location.LOCATION";
|
||||
|
||||
public LocationClient(Context context, ConnectionCallbacks callbacks) {
|
||||
googleApiClient = new GoogleApiClient.Builder(context)
|
||||
public LocationClient(Context context, ConnectionCallbacks callbacks,
|
||||
OnConnectionFailedListener connectionFailedListener) {
|
||||
super(new GoogleApiClient.Builder(context)
|
||||
.addApi(LocationServices.API)
|
||||
.addConnectionCallbacks(new ForwardConnectionCallbacks(callbacks))
|
||||
.build();
|
||||
.addOnConnectionFailedListener(new ForwardConnectionFailedListener(connectionFailedListener))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
googleApiClient.connect();
|
||||
public Location getLastLocation() {
|
||||
return LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
googleApiClient.disconnect();
|
||||
public PendingResult requestLocationUpdates(LocationRequest request, LocationListener listener) {
|
||||
return LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return googleApiClient.isConnected();
|
||||
public PendingResult requestLocationUpdates(LocationRequest request, LocationListener listener, Looper looper) {
|
||||
return LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, listener, looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnecting() {
|
||||
return googleApiClient.isConnecting();
|
||||
public PendingResult requestLocationUpdates(LocationRequest request, PendingIntent callbackIntent) {
|
||||
return LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, callbackIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionCallbacks(final ConnectionCallbacks listener) {
|
||||
googleApiClient.registerConnectionCallbacks(new ForwardConnectionCallbacks(listener));
|
||||
public PendingResult removeLocationUpdates(LocationListener listener) {
|
||||
return LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
|
||||
return googleApiClient
|
||||
.isConnectionCallbacksRegistered(new ForwardConnectionCallbacks(listener));
|
||||
public PendingResult removeLocationUpdates(PendingIntent callbackIntent) {
|
||||
return LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, callbackIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionCallbacks(
|
||||
ConnectionCallbacks listener) {
|
||||
googleApiClient.unregisterConnectionCallbacks(new ForwardConnectionCallbacks(listener));
|
||||
public PendingResult setMockMode(boolean isMockMode) {
|
||||
return LocationServices.FusedLocationApi.setMockMode(googleApiClient, isMockMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionFailedListener(
|
||||
OnConnectionFailedListener listener) {
|
||||
googleApiClient.registerConnectionFailedListener(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
public PendingResult setMockLocation(Location mockLocation) {
|
||||
return LocationServices.FusedLocationApi.setMockLocation(googleApiClient, mockLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionFailedListenerRegistered(
|
||||
OnConnectionFailedListener listener) {
|
||||
return googleApiClient.isConnectionFailedListenerRegistered(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionFailedListener(
|
||||
OnConnectionFailedListener listener) {
|
||||
googleApiClient.unregisterConnectionFailedListener(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,18 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
/**
|
||||
* Used for receiving notifications from the {@link FusedLocationProviderApi} when the location has
|
||||
* changed. The methods are called if the LocationListener has been registered with the location
|
||||
* client.
|
||||
*/
|
||||
public interface LocationListener {
|
||||
|
||||
/**
|
||||
* Called when the location has changed.
|
||||
*
|
||||
* @param location The updated location.
|
||||
*/
|
||||
public void onLocationChanged(Location location);
|
||||
}
|
||||
|
20
src/main/res/values/version.xml
Normal file
20
src/main/res/values/version.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright 2014-2015 µg Project Team
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="google_play_services_version">6599436</integer>
|
||||
</resources>
|
@ -30,14 +30,24 @@ import com.google.android.gms.common.api.Result;
|
||||
|
||||
import org.microg.gms.common.api.GoogleApiClientImpl;
|
||||
|
||||
public class GmsConnector {
|
||||
public static <C extends ApiConnection, R extends Result, O extends Api.ApiOptions>
|
||||
AbstractPendingResult<R> connect(GoogleApiClient apiClient, Api<O> api, Callback<C, R> callback) {
|
||||
public class GmsConnector<C extends ApiConnection, R extends Result, O extends Api.ApiOptions> {
|
||||
private final GoogleApiClientImpl apiClient;
|
||||
private final Api<O> api;
|
||||
private final Callback<C, R> callback;
|
||||
|
||||
public GmsConnector(GoogleApiClient apiClient, Api<O> api, Callback<C, R> callback) {
|
||||
this.apiClient = (GoogleApiClientImpl) apiClient;
|
||||
this.api = api;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
|
||||
public AbstractPendingResult<R> connect() {
|
||||
Looper looper = ((GoogleApiClientImpl) apiClient).getLooper();
|
||||
final AbstractPendingResult<R> result = new AbstractPendingResult<>(looper);
|
||||
Message msg = new Message();
|
||||
msg.obj = new ConnectRequest<C, R, O>((GoogleApiClientImpl) apiClient, api, result, callback);
|
||||
new Handler<C, R, O>(looper).sendMessage(msg);
|
||||
msg.obj = result;
|
||||
new Handler(looper).sendMessage(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -45,35 +55,21 @@ public class GmsConnector {
|
||||
public R onClientAvailable(C client) throws RemoteException;
|
||||
}
|
||||
|
||||
private static class Handler<C extends ApiConnection, R extends Result, O extends Api.ApiOptions> extends android.os.Handler {
|
||||
private class Handler extends android.os.Handler {
|
||||
private Handler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
ConnectRequest<C, R, O> request = (ConnectRequest<C, R, O>) msg.obj;
|
||||
ApiConnection apiConnection = request.apiClient.getApiConnection(request.api);
|
||||
AbstractPendingResult<R> result = (AbstractPendingResult<R>) msg.obj;
|
||||
ApiConnection apiConnection = apiClient.getApiConnection(api);
|
||||
apiConnection.connect();
|
||||
try {
|
||||
request.result.setResult(request.callback.onClientAvailable((C) apiConnection));
|
||||
result.setResult(callback.onClientAvailable((C) apiConnection));
|
||||
} catch (RemoteException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConnectRequest<C extends ApiConnection, R extends Result, O extends Api.ApiOptions> {
|
||||
GoogleApiClientImpl apiClient;
|
||||
Api<O> api;
|
||||
AbstractPendingResult<R> result;
|
||||
Callback<C, R> callback;
|
||||
|
||||
private ConnectRequest(GoogleApiClientImpl apiClient, Api<O> api, AbstractPendingResult<R> result, Callback<C, R> callback) {
|
||||
this.apiClient = apiClient;
|
||||
this.api = api;
|
||||
this.result = result;
|
||||
this.callback = callback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2014-2015 µg Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.common.api;
|
||||
|
||||
import com.google.android.gms.common.GooglePlayServicesClient;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
|
||||
import org.microg.gms.common.ForwardConnectionCallbacks;
|
||||
import org.microg.gms.common.ForwardConnectionFailedListener;
|
||||
|
||||
public class AbstractPlayServicesClient implements GooglePlayServicesClient {
|
||||
|
||||
protected final GoogleApiClient googleApiClient;
|
||||
|
||||
public AbstractPlayServicesClient(GoogleApiClient googleApiClient) {
|
||||
this.googleApiClient = googleApiClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
googleApiClient.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
googleApiClient.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return googleApiClient.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnecting() {
|
||||
return googleApiClient.isConnecting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionCallbacks(final ConnectionCallbacks listener) {
|
||||
googleApiClient.registerConnectionCallbacks(new ForwardConnectionCallbacks(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
|
||||
return googleApiClient
|
||||
.isConnectionCallbacksRegistered(new ForwardConnectionCallbacks(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionCallbacks(
|
||||
ConnectionCallbacks listener) {
|
||||
googleApiClient.unregisterConnectionCallbacks(new ForwardConnectionCallbacks(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionFailedListener(
|
||||
OnConnectionFailedListener listener) {
|
||||
googleApiClient.registerConnectionFailedListener(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionFailedListenerRegistered(
|
||||
OnConnectionFailedListener listener) {
|
||||
return googleApiClient.isConnectionFailedListenerRegistered(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionFailedListener(
|
||||
OnConnectionFailedListener listener) {
|
||||
googleApiClient.unregisterConnectionFailedListener(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
}
|
@ -5,13 +5,18 @@ import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.common.api.PendingResult;
|
||||
import com.google.android.gms.common.api.Result;
|
||||
import com.google.android.gms.common.api.Status;
|
||||
import com.google.android.gms.location.FusedLocationProviderApi;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
|
||||
import org.microg.gms.common.GmsConnector;
|
||||
import org.microg.gms.common.api.ApiConnection;
|
||||
|
||||
public class FusedLocationProviderApiImpl implements FusedLocationProviderApi {
|
||||
private static final String TAG = "GmsFusedApiImpl";
|
||||
@ -27,49 +32,98 @@ public class FusedLocationProviderApiImpl implements FusedLocationProviderApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
LocationListener listener) {
|
||||
|
||||
//LocationClientImpl.get(client).requestLocationUpdates(request, listener);
|
||||
return null;
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client,
|
||||
final LocationRequest request,
|
||||
final LocationListener listener) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.requestLocationUpdates(request, listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
LocationListener listener, Looper looper) {
|
||||
//LocationClientImpl.get(client).requestLocationUpdates(request, listener, looper);
|
||||
return null;
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client,
|
||||
final LocationRequest request,
|
||||
final LocationListener listener,
|
||||
final Looper looper) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.requestLocationUpdates(request, listener, looper);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
PendingIntent callbackIntent) {
|
||||
//LocationClientImpl.get(client).requestLocationUpdates(request, callbackIntent);
|
||||
return null;
|
||||
}
|
||||
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client,
|
||||
final LocationRequest request,
|
||||
final PendingIntent callbackIntent) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client, LocationListener listener) {
|
||||
//LocationClientImpl.get(client).removeLocationUpdates(listener);
|
||||
return null;
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.requestLocationUpdates(request, callbackIntent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client,
|
||||
PendingIntent callbackIntent) {
|
||||
//LocationClientImpl.get(client).removeLocationUpdates(callbackIntent);
|
||||
return null;
|
||||
final LocationListener listener) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.removeLocationUpdates(listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult setMockMode(GoogleApiClient client, boolean isMockMode) {
|
||||
//LocationClientImpl.get(client).setMockMode(isMockMode);
|
||||
return null;
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client,
|
||||
final PendingIntent callbackIntent) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.removeLocationUpdates(callbackIntent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult setMockLocation(GoogleApiClient client, Location mockLocation) {
|
||||
//LocationClientImpl.get(client).setMockLocation(mockLocation);
|
||||
return null;
|
||||
public PendingResult setMockMode(GoogleApiClient client, final boolean isMockMode) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.setMockMode(isMockMode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult setMockLocation(GoogleApiClient client, final Location mockLocation) {
|
||||
return callVoid(client, new Runnable() {
|
||||
@Override
|
||||
public void run(LocationClientImpl client) throws RemoteException {
|
||||
client.setMockLocation(mockLocation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private PendingResult callVoid(GoogleApiClient client, final Runnable runnable) {
|
||||
return new GmsConnector<>(client, LocationServices.API,
|
||||
new GmsConnector.Callback<LocationClientImpl, Result>() {
|
||||
@Override
|
||||
public Result onClientAvailable(LocationClientImpl client) throws
|
||||
RemoteException {
|
||||
runnable.run(client);
|
||||
return Status.SUCCESS;
|
||||
}
|
||||
}).connect();
|
||||
}
|
||||
|
||||
private interface Runnable {
|
||||
public void run(LocationClientImpl client) throws RemoteException;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,12 +5,18 @@ import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.location.ILocationListener;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
|
||||
import org.microg.gms.common.api.GoogleApiClientImpl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LocationClientImpl extends GoogleLocationManagerClient {
|
||||
public LocationClientImpl(Context context) {
|
||||
super(context);
|
||||
@ -24,38 +30,49 @@ public class LocationClientImpl extends GoogleLocationManagerClient {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<LocationListener, ILocationListener> listenerMap = new HashMap<>();
|
||||
|
||||
public Location getLastLocation() throws RemoteException {
|
||||
return getServiceInterface().getLastLocation();
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(LocationRequest request, LocationListener listener)
|
||||
public void requestLocationUpdates(LocationRequest request, final LocationListener listener)
|
||||
throws RemoteException {
|
||||
|
||||
ILocationListener iLocationListener = new ILocationListener.Stub() {
|
||||
@Override
|
||||
public void onLocationChanged(Location location) throws RemoteException {
|
||||
listener.onLocationChanged(location);
|
||||
}
|
||||
};
|
||||
listenerMap.put(listener, iLocationListener);
|
||||
getServiceInterface().requestLocationUpdatesWithPackage(request,
|
||||
iLocationListener, getContext().getPackageName());
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(LocationRequest request, PendingIntent pendingIntent)
|
||||
throws RemoteException {
|
||||
|
||||
getServiceInterface().requestLocationUpdatesWithIntent(request, pendingIntent);
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(LocationRequest request, LocationListener listener,
|
||||
Looper looper) throws RemoteException {
|
||||
|
||||
requestLocationUpdates(request, listener); // TODO
|
||||
}
|
||||
|
||||
public void removeLocationUpdates(LocationListener listener) throws RemoteException {
|
||||
|
||||
getServiceInterface().removeLocationUpdatesWithListener(listenerMap.get(listener));
|
||||
listenerMap.remove(listener);
|
||||
}
|
||||
|
||||
public void removeLocationUpdates(PendingIntent pendingIntent) throws RemoteException {
|
||||
|
||||
getServiceInterface().removeLocationUpdatesWithIntent(pendingIntent);
|
||||
}
|
||||
|
||||
public void setMockMode(boolean isMockMode) throws RemoteException {
|
||||
|
||||
getServiceInterface().setMockMode(isMockMode);
|
||||
}
|
||||
|
||||
public void setMockLocation(Location mockLocation) throws RemoteException {
|
||||
|
||||
getServiceInterface().setMockLocation(mockLocation);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user