I am facing issues with appium test groups. I have written multiple test cases for my app and running different sets at a time.
Basically, my test flow is: Login with Google => Input Password => Logout
Then for another set same flow with Login with Facebook.
Following is the code is written in AppiumTest.java file
#Test
public class AppiumTest {
IOSDriver<MobileElement> driver = null;
public DesiredCapabilities capabilitiesForDevice(String deviceCode) {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("udid", "SOME_VALID_UDID"); // 7+
capabilities.setCapability("platformVersion", "10.3.3");
capabilities.setCapability("app", "PACKAGE_PATH");
capabilities.setCapability("noReset", false);
capabilities.setCapability("showXcodeLog", true);
capabilities.setCapability("clearSystemFiles", false);
...
return capabilities;
}
#BeforeSuite(groups = {"google"}) // Removing suite also does not make any effect
public void setup() throws MalformedURLException {
System.out.print("Setting up driver.\n");
DesiredCapabilities capabilities = capabilitiesForDevice("iPhone5s");
String url = "http://0.0.0.0:4723/wd/hub";
driver = new IOSDriver<MobileElement>(new URL(url), capabilities);
}
#AfterSuite(groups = {"facebook"})
// Removing suite also does not make any effect
// Between 2 tests execution this method is not being called
public void tearDown() {
System.out.println("AfterSuite ... QUITTING DRIVER...");
driver.quit();
}
public MobileElement getElementByName(String name) {
try {
MobileElement theElement = (MobileElement) (new WebDriverWait(driver, 30))
.until(ExpectedConditions.visibilityOfElementLocated(By.name(name)));
return theElement;
} catch (Exception e) {
// e.printStackTrace();
}
return null;
}
public MobileElement getElementByXPath(String xpath) {
try {
MobileElement theElement = (MobileElement) (new WebDriverWait(driver, 30))
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
return theElement;
} catch (Exception e) {
// e.printStackTrace();
}
return null;
}
#Test(groups = {"google"}, priority = 1)
public void loginWithGoogle() {
if (driver == null) {
printLog("Test driver is null.");
try {
setup();
} catch (MalformedURLException e) {
// e.printStackTrace();
}
}
printLog("driver = " + driver);
printLog("\nLoading is null and not logged in.." + System.currentTimeMillis());
String googleIcon = "icon google";
MobileElement gLoginElement = getElementByName(googleIcon);
gLoginElement.click();
printLog("\nGoogle clicked.." + System.currentTimeMillis());
...
// Input Credentials for Google auth or select user from the auth list
// Assert.assertEquals("Hi test found.", "Test", "Test1");
}
public void loginWithIncorrectPassword() {
String passwordEntry = "//XCUIElementTypeApplication[#name=\"eCare Vault\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[1]/XCUIElementTypeSecureTextField";
MobileElement pwdEntryElement = getElementByXPath(passwordEntry);
String passwordString = "12345";
pwdEntryElement.sendKeys(passwordString);
printLog("\n{Priority=>2} Password entered..." + passwordString + " # " + System.currentTimeMillis());
...
printLog("\nSend clicked..." + System.currentTimeMillis());
// Assert for incorrect pwd.
}
#Test(groups = {"google"}, priority = 12)
public void loginWithIncorrectPasswordGoogle() {
loginWithIncorrectPassword();
}
public void loginWithCorrectPassword() {
String passwordEntry = "//XCUIElementTypeApplication[#name=\"eCare Vault\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[1]/XCUIElementTypeSecureTextField";
MobileElement pwdEntryElement = getElementByXPath(passwordEntry);
String passwordString = "VALID PWD";
pwdEntryElement.sendKeys(passwordString);
printLog("\n{Priority=>6} Password entered..." + passwordString + " # " + System.currentTimeMillis());
// XCUIElementTypeButton[#name="Send"]
String sendKey = "Send";
MobileElement sendKeyElement = getElementByName(sendKey);
sendKeyElement.click();
printLog("\nSend clicked..." + System.currentTimeMillis());
}
#Test(groups = {"google"}, priority = 16)
public void loginWithCorrectPasswordGoogle() {
loginWithCorrectPassword();
}
public void logoutButtonClicked() {
// This method will logout user from the app and loads the main screen from where user will be able to tap the Google/Facebook icon
System.out.println("\nLogged out from ECV..." + System.currentTimeMillis());
}
#Test(groups = {"google"}, priority = 19)
public void logoutButtonClickedGoogle() {
logoutButtonClicked();
}
#Test(groups = {"facebook"}, priority = 20)
public void loginWithFB() {
System.out.println("\nLogin with Facebook..." + System.currentTimeMillis());
if (driver == null) {
printLog("Test driver is null.");
try {
setup();
} catch (MalformedURLException e) {
// e.printStackTrace();
}
}
printLog("driver = " + driver);
System.out.println("\nLoading is null and not logged in.." + System.currentTimeMillis());
String fbIcon = "icon facebook";
MobileElement fbLoginElement = getElementByName(fbIcon);
fbLoginElement.click();
System.out.println("\nFacebook clicked.." + System.currentTimeMillis());
...
// "Log In with the Facebook App" button exists for FB app login
// "Log In with the Facebook App" -> Tap
...
continueLoginElement.click();
System.out.println("\nKalis loggedIn.." + System.currentTimeMillis());
}
System.out.println(
"\n{Priority=>1} Password screen found.." + pwdScreen.getText() + " " + System.currentTimeMillis());
// Assert.assertEquals("Hi test found.", "Test", "Test1");
}
#Test(groups = {"facebook"}, priority = 22)
public void loginWithIncorrectPasswordFB() {
loginWithIncorrectPassword();
}
#Test(groups = {"facebook"}, priority = 26)
public void loginWithCorrectPasswordFB() {
loginWithCorrectPassword();
}
#Test(groups = {"facebook"}, priority = 28)
public void homePageLoadedFB() {
homePageLoaded();
}
#Test(groups = {"facebook"}, priority = 29)
public void logoutButtonClickedFB() {
logoutButtonClicked();
}
private void printLog(String message) {
System.out.println(message);
}
}
Testng.xml example
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="TestGoogle">
<groups>
<run>
<include name="google" />
</run>
</groups>
<classes>
<class name="login.googleLogin.AppiumTest" />
</classes>
</test> <!-- Test -->
<test name="TestFB">
<groups>
<run>
<include name="facebook" />
</run>
</groups>
<classes>
<class name="login.googleLogin.AppiumTest" />
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
When I right click on testng.xml and run the test as TestNG Suite, the app gets restarted when the first test "TestGoogle" is completed and there after a 5-10 seconds restarts, the app continues running and executes pending test cases for "TestFacebook".
When I combine Facebook and Google, test cases for Google/Facebook are not executed.
<run>
<include name="google" />
<include name="facebook" />
</run>
Please give me hint of how to solve the issue.
Related
Integrating facebook as an auth provider within firebase (already have a working gmail implementation). The below code works fine in Unity, the FB SDK prompts for token, enter it manually, token is passed to firebase, login can be seen in the console, the required scene is then loaded.
When this is built onto an android device the full behavior doesnt happen, the correct Facebook token is received either from fresh login or existing login, we enter the SignInWithFacebookOnFirebase function to log this account into firebase and nothing else happens, sits on the debug of ("your token is " + aToken);
Im pretty sure it has something to do with the async behaviour and maybe not awaiting the task but im not sure what, any suggestions would be great !
using System.Collections.Generic;
using UnityEngine;
using Facebook.Unity;
using TMPro;
using UnityEngine.SceneManagement;
using Firebase.Auth;
using Firebase;
public class FacebookAuth : MonoBehaviour
{
private FirebaseAuth auth;
public TMP_Text debug;
void Awake ()
{
if (FB.IsInitialized) {
FB.ActivateApp();
} else {
//Handle FB.Init
FB.Init( () => {
FB.ActivateApp();
});
}
CheckFirebaseDependencies();
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
debug.text =("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
debug.text =("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
void OnApplicationPause (bool pauseStatus)
{
// Check the pauseStatus to see if we are in the foreground
// or background
if (!pauseStatus) {
//app resume
if (FB.IsInitialized) {
FB.ActivateApp();
} else {
//Handle FB.Init
FB.Init( () => {
FB.ActivateApp();
});
}
}
}
private void InitCallBack()
{
if(!FB.IsInitialized)
{
FB.ActivateApp();
}
else
{
// debug.text=("Failed to initialize");
}
}
private void OnHideUnity(bool isgameshown)
{
if(!isgameshown)
{
Time.timeScale = 0;
}
else
{
Time.timeScale = 1;
}
}
public void Facebook_Login()
{
var permission = new List<string>() { "public_profile", "email" };
if (!FB.IsLoggedIn)
{
FB.LogInWithReadPermissions(permission, AuthCallBack);
}
else
{
var aToken = AccessToken.CurrentAccessToken.TokenString;
debug.text=("already logged in - starting game" + aToken);
//THIS IS THE PROBLEM ON ANDROID - ITS NOT HAPPENING/async issue?
SignInWithFacebookOnFirebase(aToken);
SceneManager.LoadScene(1);
}
}
public void LogOut()
{
FB.LogOut();
debug.text=("Logged out of facebook");
}
private void SignInWithFacebookOnFirebase(string idToken)
{
Firebase.Auth.Credential credential = Firebase.Auth.FacebookAuthProvider.GetCredential(idToken);
auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("SignInWithCredentialAsync was canceled.");
return;
}
if (task.Exception != null) {
Debug.LogWarning("SignInWithCredentialAsync encountered an error: " + task.Exception);
FirebaseException firebaseEx = task.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseEx.ErrorCode;
string message = "Login Failed!";
switch (errorCode)
{
case AuthError.AccountExistsWithDifferentCredentials:
message = "Your account is already linked to an email address";
break;
//we can add other conditions here if required to catch exceptions
}
debug.text=(message);
}
else{
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
debug.text=("Logged into facebook");
}
});
}
private void AuthCallBack(ILoginResult result)
{
if(FB.IsLoggedIn)
{
var aToken = result.AccessToken.TokenString;
debug.text=("your token is " + aToken);
//THIS IS THE PROBLEM ON ANDROID - ITS NOT HAPPENING/async issue?
SignInWithFacebookOnFirebase(aToken);
debug.text=("weve signed into firebase");
SceneManager.LoadScene(1);
}
else
{
debug.text=("User Cancelled login");
}
}
}
EDIT - So the problem is nothing to do with async, its the fact that the firebase credential is being persisted on the mobile device. I uncommented all of my already working google auth code below and we log into firebase with our facebook creds fine! So i need some method of clearing our this token when A) the user logs out and B) the user closes the app (Cleanly or uncleanly) Any help would be great !
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Firebase;
using Firebase.Auth;
using Google;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GoogleAuth : MonoBehaviour
{ /*
public TMP_Text infoText;
public string webClientId = "<your client id here>";
private FirebaseAuth auth;
private GoogleSignInConfiguration configuration;
private void Awake()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
CheckFirebaseDependencies();
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
AddToInformation("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
AddToInformation("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
public void SignInWithGoogle() { OnSignIn(); }
public void SignOutFromGoogle() { OnSignOut(); }
private void OnSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void OnSignOut()
{
AddToInformation("Calling SignOut");
GoogleSignIn.DefaultInstance.SignOut();
}
public void OnDisconnect()
{
GoogleSignIn.DefaultInstance.Disconnect();
infoText.text=("signed out");
}
internal void OnAuthenticationFinished(Task<GoogleSignInUser> task)
{
if (task.IsFaulted)
{
using (IEnumerator<Exception> enumerator = task.Exception.InnerExceptions.GetEnumerator())
{
if (enumerator.MoveNext())
{
GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current;
AddToInformation("Got Error: " + error.Status + " " + error.Message);
}
else
{
AddToInformation("Got Unexpected Exception?!?" + task.Exception);
}
}
}
else if (task.IsCanceled)
{
AddToInformation("Cancelled");
}
else
{
AddToInformation("Welcome: " + task.Result.DisplayName + "!");
AddToInformation("Email = " + task.Result.Email);
//AddToInformation("Google ID Token = " + task.Result.IdToken);
AddToInformation("Email = " + task.Result.Email);
SignInWithGoogleOnFirebase(task.Result.IdToken);
}
}
private void SignInWithGoogleOnFirebase(string idToken)
{
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
AggregateException ex = task.Exception;
if (ex != null)
{
if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0))
AddToInformation("\nError code = " + inner.ErrorCode + " Message = " + inner.Message);
}
else
{
AddToInformation("Sign In Successful.");
SceneManager.LoadScene(1);
}
});
}
public void OnSignInSilently()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn Silently");
GoogleSignIn.DefaultInstance.SignInSilently().ContinueWith(OnAuthenticationFinished);
}
public void OnGamesSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = true;
GoogleSignIn.Configuration.RequestIdToken = false;
AddToInformation("Calling Games SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void AddToInformation(string str) { infoText.text += "\n" + str; } */
}
this is solved, it was because i was checking that the firebase dependences existed in both these scripts and it was throwing an exception. I found this using the logcat logs \adb logcat -s Unity ActivityManager PackageManager dalvikvm DEBUG
I am developing an app in unity. I use the firebase google login method. basically google login is working and the user was listed in google firebase users log after login. the problem is, it is throwing an error. because of this can't fetch data from the firestore. even without firestore code, the app is showing the error
Got Error: DeveloperError Exception of type
'Google.GoogleSignIn+SignInException' was thrown
what may be the problem.
below is my code
public class GoogleSignInDemo : MonoBehaviour
{
public Text infoText;
private string webClientId = "xxxxxxaaaaaaabbbb.apps.googleusercontent.com";
private FirebaseAuth auth;
private GoogleSignInConfiguration configuration;
private void Awake()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
CheckFirebaseDependencies();
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
AddToInformation("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
AddToInformation("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
public void SignInWithGoogle() { OnSignIn(); }
public void SignOutFromGoogle() { OnSignOut(); }
private void OnSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void OnSignOut()
{
AddToInformation("Calling SignOut");
GoogleSignIn.DefaultInstance.SignOut();
}
public void OnDisconnect()
{
AddToInformation("Calling Disconnect");
GoogleSignIn.DefaultInstance.Disconnect();
}
internal void OnAuthenticationFinished(Task<GoogleSignInUser> task)
{
if (task.IsFaulted)
{
using (IEnumerator<Exception> enumerator = task.Exception.InnerExceptions.GetEnumerator())
{
if (enumerator.MoveNext())
{
GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current;
AddToInformation("Got Error: " + error.Status + " " + error.Message);
}
else
{
AddToInformation("Got Unexpected Exception?!?" + task.Exception);
}
}
}
else if (task.IsCanceled)
{
AddToInformation("Canceled");
}
else
{
AddToInformation("Welcome: " + task.Result.DisplayName + "!");
AddToInformation("Email = " + task.Result.Email);
AddToInformation("Google ID Token = " + task.Result.IdToken);
AddToInformation("Email = " + task.Result.Email);
SignInWithGoogleOnFirebase(task.Result.IdToken);
SceneManager.LoadScene(1); //Savad - Load Welcome screen when Google Login
}
}
private void SignInWithGoogleOnFirebase(string idToken)
{
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
AggregateException ex = task.Exception;
//==============Here is the problem
if (ex != null)
{
if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0))
AddToInformation("\nError code = " + inner.ErrorCode + " Message = " + inner.Message);
//=======================================
}
else
{
AddToInformation("Sign In Successful.");
}
});
}
public void OnSignInSilently()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn Silently");
GoogleSignIn.DefaultInstance.SignInSilently().ContinueWith(OnAuthenticationFinished);
}
public void OnGamesSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = true;
GoogleSignIn.Configuration.RequestIdToken = false;
AddToInformation("Calling Games SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void AddToInformation(string str) { infoText.text += "\n" + str; }
public void SwitchToPhoneSignup()
{
SceneManager.LoadScene(2);
}
public void SwitchToOtp()
{
SceneManager.LoadScene(2);
}
public void SwitchToEmailSignUP()
{
SceneManager.LoadScene(2);
}
}
Here is a working example of Google SignIn code w/ Firebase Authentication and GoogleSignIn libraries:
private void SignInWithGoogle(bool linkWithCurrentAnonUser)
{
GoogleSignIn.Configuration = new GoogleSignInConfiguration
{
RequestIdToken = true,
// Copy this value from the google-service.json file.
// oauth_client with type == 3
WebClientId = "[YOUR API CLIENT ID HERE].apps.googleusercontent.com"
};
Task<GoogleSignInUser> signIn = GoogleSignIn.DefaultInstance.SignIn();
TaskCompletionSource<FirebaseUser> signInCompleted = new TaskCompletionSource<FirebaseUser>();
signIn.ContinueWith(task =>
{
if (task.IsCanceled)
{
signInCompleted.SetCanceled();
}
else if (task.IsFaulted)
{
signInCompleted.SetException(task.Exception);
}
else
{
Credential credential = Firebase.Auth.GoogleAuthProvider.GetCredential(((Task<GoogleSignInUser>)task).Result.IdToken, null);
if (linkWithCurrentAnonUser)
{
mAuth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(HandleLoginResult);
}
else
{
SignInWithCredential(credential);
}
}
});
}
The parameter is for signing in with intentions of linking the new google account with an anonymous user that is currently logged on. You can ignore those parts of the method if desired. Please note all of this is called after proper initialization of the Firebase Auth libraries.
Source: https://github.com/googlesamples/google-signin-unity
The readme page contains a step-by-step instructions for getting this setup for your environment. After following those and using the code above, you should have this working on both android and iOS.
Here is the SignInWithCredential method used in the code above:
private void SignInWithCredential(Credential credential)
{
if (mAuth != null)
{
mAuth.SignInWithCredentialAsync(credential).ContinueWith(HandleLoginResult);
}
}
`mAuth` is a reference to FirebaseAuth:
mAuth = Firebase.Auth.FirebaseAuth.DefaultInstance;
For someone asking for the HandleLoginResult from #DIGI Byte, here is the code, feel free to remove try/catch block for debug purpose:
private void HandleLoginResult(Task<FirebaseUser> task)
{
try
{
if (task.IsCanceled)
{
UnityEngine.Debug.LogError("SignInWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
UnityEngine.Debug.LogError("SignInWithCredentialAsync encountered an error: " + task.Exception.InnerException.Message);
return;
}
else
{
FirebaseUser newUser = task.Result;
UnityEngine.Debug.Log($"User signed in successfully: {newUser.DisplayName} ({newUser.UserId})");
}
}
catch (Exception e)
{
if (e != null)
{
UnityEngine.Debug.Log(e.InnerException.Message);
}
}
}
You have Error like: got error developer error exception of type 'google.googlesignin+signin exception' was thrown?
APK and AAB file have different SHA1 and SHA256. In Firebase, it's best to add SHA for both applications.
You can check the SHA from the AAB file in Google Play Console -> Your application -> Configuration -> Application integrity -> Application signing.
I added these SHA keys to Firebase and the problem was gone.
In a REST service adding a circuit breaker with hystrix, I could do the following:
#HystrixCommand(fallbackMethod = "getBackupResult")
#GetMapping(value = "/result")
public ResponseEntity<ResultDto> getResult(#RequestParam("request") String someRequest) {
ResultDto resultDto = service.parserRequest(someRequest);
return new ResponseEntity<>(resultDto, HttpStatus.OK);
}
public ResponseEntity<ResultDto> getBackupResult(#RequestParam("request") String someRequest) {
ResultDto resultDto = new ResultDto();
return new ResponseEntity<>(resultDto, HttpStatus.OK);
}
Is there something similar I can do for the gRPC call?
public void parseRequest(ParseRequest request, StreamObserver<ParseResponse> responseObserver) {
try {
ParseResponse parseResponse = service.parseRequest(request.getSomeRequest());
responseObserver.onNext(parseResponse);
responseObserver.onCompleted();
} catch (Exception e) {
logger.error("Failed to execute parse request.", e);
responseObserver.onError(new StatusException(Status.INTERNAL));
}
}
I solved my problem by implementing the circuit-breaker on my client. I used the sentinel library
To react on exceptions ratio for example I added this rule:
private static final String KEY = "callGRPC";
private void callGRPC(List<String> userAgents) {
initDegradeRule();
ManagedChannel channel = ManagedChannelBuilder.forAddress(grpcHost, grpcPort).usePlaintext()
.build();
for (String userAgent : userAgents) {
Entry entry = null;
try {
entry = SphU.entry(KEY);
UserAgentServiceGrpc.UserAgentServiceBlockingStub stub
= UserAgentServiceGrpc.newBlockingStub(channel);
UserAgentParseRequest request = UserAgentRequest.newBuilder().setUserAgent(userAgent).build();
UserAgentResponse userAgentResponse = stub.getUserAgentDetails(request);
} catch (BlockException e) {
logger.error("Circuit-breaker is on and the call has been blocked");
} catch (Throwable t) {
logger.error("Exception was thrown", t);
} finally {
if (entry != null) {
entry.exit();
}
}
}
channel.shutdown();
}
private void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<DegradeRule>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
rule.setCount(0.5);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setTimeWindow(60);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
I want to show dialogue when new version is available.
I want to make a json file into my web server, and I will manually update my app version in json file. and my app will parse this json file and will notify users and showing dialogue box to update my app from playstore link by clicking Update button.
I don't want to make this with firebase.
public class ForceUpdateAsync extends AsyncTask<String, String, JSONObject>{
private String latestVersion;
private String currentVersion;
private Context context;
public ForceUpdateAsync(String currentVersion, Context context){
this.currentVersion = currentVersion;
this.context = context;
}
#Override
protected JSONObject doInBackground(String... params) {
try
{
latestVersion = Jsoup.connect("https://play.google.com/store/apps/details?id="+context.getPackageName()+"&hl=en")
.timeout(30000)
.userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6")
.referrer("http://www.google.com")
.get()
.select("div[itemprop=softwareVersion]")
.first()
.ownText();
} catch (IOException e) {
e.printStackTrace();
}
return new JSONObject();
}
#Override
protected void onPostExecute(JSONObject jsonObject) {
if(latestVersion!=null){
if(!currentVersion.equalsIgnoreCase(latestVersion)){
// Toast.makeText(context,"update is available.",Toast.LENGTH_LONG).show();
if(!(context instanceof SplashActivity)) {
if(!((Activity)context).isFinishing()){
showForceUpdateDialog();
}
}
}
}
super.onPostExecute(jsonObject);
}
public void showForceUpdateDialog(){
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(new ContextThemeWrapper(context,
R.style.DialogDark));
alertDialogBuilder.setTitle(context.getString(R.string.youAreNotUpdatedTitle));
alertDialogBuilder.setMessage(context.getString(R.string.youAreNotUpdatedMessage) + " " + latestVersion + context.getString(R.string.youAreNotUpdatedMessage1));
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setPositiveButton(R.string.update, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName())));
dialog.cancel();
}
});
alertDialogBuilder.show();
}
}
after that in your splash activity just use this code
public void forceUpdate()
{
PackageManager packageManager = this.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = packageManager.getPackageInfo(getPackageName(),0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
String currentVersion = packageInfo.versionName;
new ForceUpdateAsync(currentVersion,BaseActivity.this).execute();
}
File newSoundFile = new File("pathFile");
if (DebugUtil.DEBUG) {
DebugUtil.logError(new Exception(), newSoundFile.getAbsolutePath());
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "Title");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.MediaColumns.SIZE, newSoundFile.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
context.getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + newSoundFile.getAbsolutePath() + "\"", null);
Uri newUri = context.getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, newUri);
KitKatToast.makeText(context, R.string.msg_setAsRingTuneSuccess, KitKatToast.LENGTH_LONG).show();
}
catch (Exception e) {
if (DebugUtil.DEBUG) {
DebugUtil.logError(new Exception(), e.toString());
}
}
I saw many posts but anyone showed what i should actually have to do. So i decided to create this complete answer. The only think you actually need is a button.
Lets start.
Here is my MainActivity.java which i used
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
b2 = (Button) findViewById(R.id.button2);
b2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent1 = new Intent();
intent1.setAction(Intent.ACTION_GET_CONTENT);
intent1.setType("audio/*");
startActivityForResult(Intent.createChooser(intent1, "Choose Sound File"), 6);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == 6) {
Uri i = data.getData(); //getDATA
String s = = i.getPath(); //getPath
File k = new File(s); //set File from path
if (s != null) { //(file.exists
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "ring");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, k.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(MainActivity.this, RingtoneManager.TYPE_RINGTONE, newUri);
} catch (Throwable t) {
}
}
}
}
}
Lastly its really important to add those permisions in your AndroidManifest.xml for example if you dont add the permision to write external storage your app will crash like mine.. xD
What you need:
<uses-permission android:name="android.permission.WRITE_SETTINGS" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" ></uses-permission>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" ></uses-permission>
You can try my app on Google Play : BackAtel Audio Manager
Hope that helps.... my problem is now solved!! i hope that i solved your problem too :))