I have deployed Parse Server on Heroku. The Mongo Lab and setup and everything is working fine. The server is successfully deployed on the parse server but I am not able to connect my android app to the parse server deployed on heroku.
I have configured the below details in my parse server index.js
var api = new ParseServer({
serverURL: "https://parseservertest12.herokuapp.com",
databaseURI: databaseUri || 'mongodb://heroku_jhwmv6c9:khhmh38a4u95krh1gbajni59rs#ds021034.mlab.com:21034/heroku_jhwmv6c9',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'myAppId',
masterKey: process.env.MASTER_KEY || 'myMasterKey' //Add your master key here. Keep it secret!
});
Check my Heroku Creditentials
Here is my Application.java Class
Parse.initialize(new Parse.Configuration.Builder(getApplicationContext())
.applicationId("myAppId")
.clientKey("myMasterKey")
.server("https://parseservertest12.herokuapp.com/parse")
.build()
);
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e == null) {
Log.i("Parse", "Save Succeeded");
} else {
Log.i("Parse", "Save Failed");
}
}
});
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
// defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
}
This is my AndroidManifest.xml
<application
android:name=".StarterApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data
android:name="com.parse.APPLICATION_ID"
android:value="#string/parse_app_id" />
<meta-data
android:name="com.parse.CLIENT_KEY"
android:value="#string/parse_client_key" />
This is the Strings.xml
<string name="parse_app_id">myAppId</string>
<string name="parse_client_key">myMasterKey</string>
I have tried resolving this issue a lot of times and referred to many online solutions but my method and everything seems correct but I am still not able to connect the android application to my parse server. My application is ready on the Android device but connecting to the parse server has caused me alot of delay please help me resolve this issue.
Running parse server with the VERBOSE=1 environment variable will help you debug this issue.
Also, can you try replacing your serverURL with https://parseservertest12.herokuapp.com/parse/ (adding a trailing /). In the android app.
Related
I am using google play services signInSilently(), but I got the error signInSilently() Failed com.google.android.gms.common.api.ApiException: 4: 4: , but I am a test user in my application. I already added SHA-1, client ID , client secret and enable sign in with google, google play game service on my firebase project. My code is below,
class SignInGGPlayBan2 : AppCompatActivity() {
private lateinit var googleSignInClient: GoogleSignInClient
private lateinit var auth: FirebaseAuth
companion object {
private val TAG = "SignInGGPlayBan2"
private const val RC_SIGN_IN = 9001
}
private var btnSignIn: SignInButton? = null
private var btnGGPlayGameSignOut: Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ggplay)
val gso = GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode(getString(R.string.default_web_client_id))
.build()
googleSignInClient = GoogleSignIn.getClient(this, gso)
auth = FirebaseAuth.getInstance()
btnSignIn = findViewById(R.id.btnGGPlayGame)
btnGGPlayGameSignOut = findViewById(R.id.btnGGPlayGameSignOut)
btnSignIn!!.setOnClickListener {
startSignInIntent()
}
}
override fun onStart() {
super.onStart()
val currentUser = auth.currentUser
updateUI(currentUser)
}
private fun startSignInIntent() {
val intent = googleSignInClient.signInIntent
startActivityForResult(intent, RC_SIGN_IN)
}
private fun signInSilently() {
googleSignInClient.silentSignIn().addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
Toast.makeText(this#SignInGGPlayBan2, "Successful", Toast.LENGTH_SHORT).show()
firebaseAuthWithPlayGames(task.result!!)
} else {
Log.d(TAG, "signInSilently() Failed", task.getException())
Toast.makeText(this#SignInGGPlayBan2, "Failed", Toast.LENGTH_SHORT).show()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
val result = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
if (result!!.isSuccess) {
firebaseAuthWithPlayGames(result.signInAccount!!)
Toast.makeText(this#SignInGGPlayBan2, "Successful Activity", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this#SignInGGPlayBan2, "Failed Activity", Toast.LENGTH_SHORT).show()
}
}
private fun firebaseAuthWithPlayGames(acct: GoogleSignInAccount) {
Log.d(TAG, "firebaseAuthWithPlayGames:" + acct.id!!)
val auth = FirebaseAuth.getInstance()
val credential = PlayGamesAuthProvider.getCredential(acct.serverAuthCode!!)
auth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
Log.d(TAG, "signInWithCredential:success")
val user = auth.currentUser
updateUI(user)
} else {
Log.w(TAG, "signInWithCredential:failure", task.exception)
Toast.makeText(baseContext, "Authentication failed.", Toast.LENGTH_SHORT).show()
updateUI(null)
}
}
}
override fun onResume() {
super.onResume()
signInSilently()
}
private fun updateUI(currentUser: FirebaseUser?) {
if (currentUser != null) {
btnGGPlayGameSignOut!!.visibility = View.VISIBLE
} else {
btnGGPlayGameSignOut!!.visibility = View.INVISIBLE
}
}
}
error
signInSilently() Failed
com.google.android.gms.common.api.ApiException: 4: 4:
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(com.google.android.gms:play-services-base##17.1.0:4)
at com.google.android.gms.common.internal.zai.zaf(com.google.android.gms:play-services-base##17.1.0:2)
at com.google.android.gms.common.internal.zak.onComplete(com.google.android.gms:play-services-base##17.1.0:6)
at com.google.android.gms.common.api.internal.BasePendingResult.zaa(com.google.android.gms:play-services-base##17.1.0:176)
at com.google.android.gms.common.api.internal.BasePendingResult.setResult(com.google.android.gms:play-services-base##17.1.0:135)
at com.google.android.gms.auth.api.signin.internal.zzi.zzc(com.google.android.gms:play-services-auth##18.0.0:5)
at com.google.android.gms.auth.api.signin.internal.zzs.dispatchTransaction(com.google.android.gms:play-services-auth##18.0.0:6)
at com.google.android.gms.internal.auth-api.zzc.onTransact(com.google.android.gms:play-services-auth##18.0.0:13)
at android.os.Binder.execTransact(Binder.java:565)
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myprojecttest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".SignInGGPlayBan2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Please give me a solution for this problem.
I have been suffering from this for a few days. And today finally I figured it out.
Three Consoles are useful here:
Firebase Console / Project Settings:
https://console.firebase.google.com
Google Developer Console / Credentials:
https://console.developers.google.com/apis/credentials
Linked Apps:
https://play.google.com/apps/publish/
Looks like you are using firebase and the same here. And of course, we will follow the guide: https://firebase.google.com/docs/auth/android/play-games?authuser=0. In my case, we are using Play Games Sign-in.
To fix those GMS ApiExceptions like DEVELOPER_ERROR (10) / INTERNAL_ERROR (8) / API_NOT_CONNECTED (17) / SIGN_IN_REQUIRED (4), follow this checklist below:
Ignore the Gradle task signingReport, this is important, or it'll create an OAuth 2.0 Client ID automatically with your.package.name and SHA1 from ~/.android/debug.keystore which is error-prone.
Create or use your own Key Store files, you can create it from Android Studio / Build / Generate Signed Bundle or APK / Create new... / Choose existing..., (here I created 2 files, one for debug and one for release, hereinafter called debug.jks and release.jks)
Get the SHA1 from debug.jks using keytool -exportcert -alias YOUR_ALIAS -keystore debug.jks -list -v, paste your debug SHA1 to your Firebase Console. Save the configuration and download the google-service.json to your Android Studio properly. Watch out, you only set the debug SHA1 but not the release one. Then Run your App, this process will create an OAuth 2.0 Client ID automatically with the debug SHA1. You can refresh the Google Developer Console / Credentials to check what you have done.
DO NOT create OAuth 2.0 Client ID from Google Developer Console / Credentials, all IDs should create automatically from Google service Or Linked Apps.
Then you should have two Client IDs on Google Developer Console / Credentials: Android client for your.package.name (auto created by Google Service) and Web client (auto created by Google Service) Check you google-service.json file, it’ll contain two client_id, both must be exactly the same as Google Developer Console / Credentials.
Make sure you settled in the Firebase console, the Authentication part.
Now let’s do Linked Apps. Just like the guide: https://firebase.google.com/docs/auth/android/play-games?authuser=0#link_your_firebase_project_to_your_play_publisher_account, but BEWARE there is a huge diff here, after clicked Authorize your app, the console try to automatically add your Google Play App Signing SHA1 as a client ID ( no the release.jks SHA1, the release.jks SHA1 is an upload key, google play will resign the APK/Bundle with its own key). Feel free to create it, and btw it’s a good hobby to rename the Linked app like ‘Your App Name - Google Play’. And Then refresh the Google Developer Console / Credentials to check.
Let’s link two more Apps, named ‘Your App Name - AdHoc’ with the SHA1 from release.jks and ‘Your App Name - Debug’ from debug.jks.
Now Generate Signed Bundle or APK. Make sure your APK file signed properly. Beware that using Android studio, Run 'YOUR_PROJECT' at debug mode will sign the APK with ~/.android/debug.keystore which SHA1 is not the one you are using to create client id.
ADB install the APK.
The Google Developer Console / Credentials should looks like this figure:
The Linked Apps should look like this figure:
Thank you GOOGLE and my fallen hair, good luck to you.
Relative Answers:
How to sign your app using the upload key
Test Google Play Games on app signed with upload key
Testing Games Services using upload key instead of Google Play App signing key
First of all, you should put this on your AndroidManifest.xml
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="#string/app_id" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
If you're using Play Games Services v2 SDK,
implementation 'com.google.android.gms:play-services-games-v2:17.0.0'
I got this error when I tried to sign-in with GoogleSignIn API and Play Games Services v2 SDK.
With v2 SDK, You can't sign-in or sign-out with GoogleSignIn API, any more. (cf. Remove sign-in and sign-out calls)
Sign-in is triggered automatically when your game is launched (for the first time), or you can trigger it manually with GamesSignInClient.signIn(). (cf. Migrate to Play Games Services Sign In v2)
So your code could be modified like:
private void startSignInIntent() {
PlayGames.getGamesSignInClient(this).signIn()
}
onResume and signInSilently (I renamed it checkAuthentication) would be modified like this:
override fun onResume() {
super.onResume()
// Since the state of the signed in user can change when the activity is not active
// it is recommended to try and sign in silently from when the app resumes.
PlayGames.getGamesSignInClient(this).isAuthenticated
.addOnCompleteListener(checkAuthentication)
}
private val checkAuthentication = OnCompleteListener<AuthenticationResult> {
if (it.isSuccessful && it.result.isAuthenticated) {
// Continue with Play Games Services
PlayGames.getPlayersClient(this).currentPlayer.addOnCompleteListener { task ->
val displayName = if (task.isSuccessful) {
task.result.displayName
} else {
handleException(
task.exception, "There was an issue communicating with players."
)
"???"
}
updateUI(displayName)
}
} else {
// Disable your integration with Play Games Services or show a
// login button to ask players to sign-in. Clicking it should
// call GamesSignInClient.signIn().
updateUI(null)
}
}
(The above modifications are for examples. It might not be applied straight foward to your code as they are.)
I think the Google's official document about Play Games Services v2 SDK has some flaws. For example:
The doc about SavedGames uses signInSilently still with v2 but it is obsolete (causing 'com.google.android.gms.common.api.ApiException: 4: 4 ').
The doc about SavedGames uses GoogleSignInClient to specify the Drive scope, but it seems not necessary (just let alone with Play Games Services Sign In v2 is sufficient).
I'm following the File transfer example on the Nearby Connections Exchange page (the "more complex example" code snippet).
I can send an image and receive it on another device in the Download/Nearby folder. The image is sent successfully since if I were to change the file name to give it an appropriate extension (e.g. .jpg), I can open the image in a photo gallery app.
private void processFilePayload(long payloadId) {
Payload filePayload = completedFilePayloads.get(payloadId);
String filename = filePayloadFilenames.get(payloadId);
if (filePayload != null && filename != null) {
completedFilePayloads.remove(payloadId);
filePayloadFilenames.remove(payloadId);
// Retrieve received file from Downloads folder
Payload.File payloadFile2 = filePayload.asFile();
File payloadJavaFile = payloadFile2.asJavaFile();
if (payloadJavaFile == null) {
Log.d(TAG, "Payload java file is null in processFilePayload()");
} else {
payloadJavaFile.renameTo(new File(payloadJavaFile.getParentFile(), filename));
}
}
}
Why is the payloadJavaFile variable null? From looking at Payload.class, I know that the result of asJavaFile() is a nullable File and that, from the asJavaFile() method description, calling asJavaFile() in processFilePayload() from within onPayloadReceived() (as is done in the example on the API page) may lead to the File not having received all of the payload's contents yet. However, I also call processFilePayload() from within onPayloadTransferUpdate() after verifying the success of the PayloadTransferUpdate, and so shouldn't the payload have received all of its contents by this stage (and not be null when calling asJavaFile() on the payload object)?
My code is almost the same as the documentation for both sending and receiving the image and file name.
Payload.asJavaFile() will be null if the READ_EXTERNAL_STORAGE permission is not properly set up for your application. You need READ_EXTERNAL_STORAGE in the AndroidManifest.xml and you need to also request READ_EXTERNAL_STORAGE permission at runtime since it is a dangerous permission. (https://developer.android.com/training/permissions/requesting)
To share files using Nearby Connections, your application will need all of the following:
AndroidManifest.xml
<!-- Required for Nearby Connections -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Optional: needed to share files -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
MainActivity.java
ActivityCompat.requestPermissions(thisActivity,
new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE
},
PERMISSIONS_REQUEST_CODE);
We will improve the documentation to make this requirement for sharing files more obvious.
I checked the source code. From what I can see, asJavaFile() is always set (and I'm not sure why it's marked as #Nullable).
Unfortunately, for me to look into it any further, I'd need you to provide me with a sample app that reproduces the bug you're seeing.
I have created Accessibility service in Android and it works perfectly on 4.2 (Jelly Bean) and 5.1 (Lollipop) but not on 4.4 (KitKat).
On KitKat, it doesn't receive ANY events and doesn't call onAccessibilityEvent at all.
Am I doing something wrong?
Here's my implementation:
accessibilityservice.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged"
android:accessibilityFeedbackType="feedbackAllMask"
android:canRetrieveWindowContent="true"
android:description="#string/app_name"
android:notificationTimeout="100" />
myAccessibilityService.java
public class myAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent e) {
if (e.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
Log.d(TAG, "NOTIFICATION!!");
}
}
#Override
protected void onServiceConnected() {
Log.d(TAG, AccessibilityService Connected");
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
info.flags = AccessibilityServiceInfo.DEFAULT;
info.notificationTimeout = 100;
setServiceInfo(info);
}
#Override
public void onInterrupt() {
Log.d(TAG, "myAccessibilityService onInterrupt Called");
}
}
AndroidManifest.xml
<service
android:name=".myAccessibilityService"
android:enabled="true"
android:label="#string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/accessibilityservice" />
</service>
When I go to settings and turn the service on, onServiceConnected is called and it says it's on and running BUT it never called onAccessibilityEvent.
Like I said, it works on JellyBean AND Lollipop. So what could be the problem?
When you create a new service info, you remove a lot of the default properties of the service info. I recommend fetching the service info of the service, and then manipulating that object. I'm not convinced this will fix your problem, but it's a better idea in general.
To clarify, I recommend exchanging this line:
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
With this:
AccessibilityServiceInfo info = this.getServiceInfo();
So that you maintain the default configuration from any XML properties, default construction, etc.
First of all, in onServiceConnected(), remove all the lines except the Log.
Your Accessibility service can miss events if you have any other accessibility service with same package name & registered for same events installed on the device.
Also,
1) Try to check other events like TYPE_WINDOW_CONTENT_CHANGED and see if KitKat device receives them.
2) Try running on a different version of KitKat (might be a version issue).
I'm creating a service as root using WakefulBroadcastReceiver approach for some test purpose (Note that I just tested with an Activity launching the server, same thing happen):
MyService.java
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Server starting");
// Create the server
server = new WebServer(6666);
new Thread(new Runnable() {
#Override
public void run() {
try {
server.start();
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
}
}).start();
...
return START_STICKY;
}
WebServer.java :
public class WebServer extends NanoHTTPD {
#Override
public Response serve(IHTTPSession session) {
Log.d(TAG, "Serving");
return new NanoHTTPD.Response("<html><body>test</body></html>");
}
I push using adb the APK in /system/app so the service can be called without using an activity first. Then restart the shell.
I can see logs of the server waiting for connection and then :
if I use wget http://127.0.0.1:6666 using adb shell I can see the log "Serving".
if I use the device browser with the same address (tried localhost too), the server isn't reached.
I use API18 and default Nexus7 AVD (tried with Genymotion too and a samsung tablet) but nothing works. There is no proxy configured in network settings.
I don't get why browser (on the device) isn't reaching my 6666 port on 127.0.0.1 (on the device too)
Here is the manifest :
<application android:allowBackup="true" android:label="#string/app_name"
android:icon="#mipmap/ic_launcher" android:theme="#style/AppTheme">
<service android:name=".MyService" android:label="Tool" android:enabled="true"/>
<receiver android:name=".receiver.BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I was running crazy and finally someone sent me this link :
https://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome
Port 6666 is considered unsafe ... I wish it would be written on the page instead of couldn't reach server.
Can anybody tell my why this doesn't work in the Android emulator? From the browser I have access and the server is internal. All I can think of is that I'm missing some configuration on my app so it can access the network layer.
try {
InetAddress server = Inet4Address.getByName("thehost");
//Doesn't work either
//or InetAddress server2 = Inet4Address.getByAddress(new String("192.168.1.30").getBytes());
if(server.isReachable(5000)){
Log.d(TAG, "Ping!");
}
Socket clientsocket = new Socket(server, 8080);
} catch (UnknownHostException e) {
Log.e(TAG, "Server Not Found");
} catch (IOException e) {
Log.e(TAG, "Couldn't open socket");
}
Throws an UnknownHostException
Thanks
As far as configuration goes, the only setting you should need to access the Internet from your application is the INTERNET permission, enabled by adding the following line outside the Application tags within your application Manifest.
<uses-permission android:name="android.permission.INTERNET" />
So the manifest would follow this general construction
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.apis">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="MyApplication"
android:label="#string/application_title"
android:icon="#drawable/my_icon">
[ .. Your Activities go here ]
</application>
</manifest>
It might still not work, because of the timeout. Since you need root permissions to send an ICMP Package and the implemetation of isReachable will use the slow TCP version of ECHO. Chekcout the javaDoc.