android - leer - Credenciales de cuenta de servicio de Firebase Json Permiso de lectura denegado
leer datos firebase android (3)
Descargué el credencial de la cuenta de servicio archivo json de la consola de Firebase que lo colocó antes en el directorio principal del proyecto de punto final de GAE. Cuando ejecuto mi respaldo local, se da una excepción de seguridad.
java.security.AccessControlException: access denied ("java.io.FilePermission" "/src/main/secret.json" "read")
Traté de colocar el archivo .json en el directorio src también, pero sin ayuda.
Debe colocar el archivo json en src/main/resources
Encontré un par de maneras de abordar esto. Lo primero es obtenerlo de un archivo a través de una transmisión de Internet. El otro es localmente
FORMA DE INTERNET
Mi primer método implicaba almacenar el archivo en mi carpeta pública de Dropbox. Obtuve el enlace que se puede compartir (asegúrese de que termine en .json
) y lo pegué en el ejemplo de cadena "https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS"
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
MyBean mModelClassObject = null;
String text = "";
try {
String line = "";
StringBuilder builder = new StringBuilder();
URL url = new URL("https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
while ((line = reader.readLine()) != null) {
// ...
builder.append(line);
}
reader.close();
text = builder.toString();
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
CAMINO LOCAL
La otra forma es tomar la versión anterior y omitir algo como dropbox
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
MyBean mModelClassObject = null;
String text = "JUST PASTE YOUR JSON CONTENTS HERE";
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
No sé si esto sigue las mejores prácticas, pero mi proyecto está funcionando ahora. También incluí el código de firebase para obtener información. mira esta respuesta a una pregunta que hice recientemente sobre leer y escribir en firebase.
EDITAR
versión limpia que no arroja errores
public class MyEndpoint {
private FirebaseOptions options;
private DatabaseReference ref;
private String serviceAccountJSON = "i took mine out for security reasons";
// create firebase instance if need be
private void connectToFirebase(){
if (options == null) {
options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(new ByteArrayInputStream(serviceAccountJSON.getBytes(StandardCharsets.UTF_8)))
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
}
if(ref == null) {
ref = FirebaseDatabase.getInstance().getReference();
}
}
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
// always do this first
connectToFirebase();
MyBean mModelClassObject = null;
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
// get the info
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
// wait for it
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
mModelClassObject.setData(mModelClassObject.getData() + name);
return mModelClassObject;
}
}
Finalmente, encontré la solución, escrita en la sección de API y referencias de Google App Engine en este enlace , que necesitamos agregar dichos archivos en el archivo appengine-web.xml bajo la etiqueta <resource-files>
, usando <include path=""/>
propiedad. Después de hacerlo, funciona para mí. Coloqué el archivo .json que contenía las credenciales del proyecto en el directorio WEB-INF y luego ingresé su ruta relativa en la etiqueta <resource-files>
.