aws-sdk-android
aws-sdk-android copied to clipboard
Getting error wrapped.errorStream must not be null while uploading files on s3 bucket
Describe the bug Getting below exception while uploading assets:
java.lang.NullPointerException: wrapped.errorStream must not be null
at com.android.tools.appinspection.network.httpurl.TrackedHttpURLConnection.getErrorStream(TrackedHttpURLConnection.kt:155)
at com.android.tools.appinspection.network.httpurl.HttpsURLConnectionWrapper.getErrorStream(HttpsURLConnectionWrapper.kt:130)
at com.amazonaws.http.UrlHttpClient.createHttpResponse(UrlHttpClient.java:94)
at com.amazonaws.http.UrlHttpClient.execute(UrlHttpClient.java:85)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:386)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:229)
at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.invoke(AmazonCognitoIdentityClient.java:1836)
at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.getCredentialsForIdentity(AmazonCognitoIdentityClient.java:750)
at com.amazonaws.auth.CognitoCredentialsProvider.populateCredentialsWithCognito(CognitoCredentialsProvider.java:791)
at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:703)
at com.amazonaws.auth.CognitoCredentialsProvider.refresh(CognitoCredentialsProvider.java:640)
at com.amazonaws.auth.CognitoCachingCredentialsProvider.refresh(CognitoCachingCredentialsProvider.java:511)
at com.amazonaws.auth.CognitoCachingCredentialsProvider.getIdentityId(CognitoCachingCredentialsProvider.java:453)
at com.amazonaws.auth.CognitoCredentialsProvider.populateCredentialsWithCognito(CognitoCredentialsProvider.java:785)
at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:703)
at com.amazonaws.auth.CognitoCredentialsProvider.refresh(CognitoCredentialsProvider.java:640)
at com.amazonaws.auth.CognitoCachingCredentialsProvider.refresh(CognitoCachingCredentialsProvider.java:511)
To Reproduce A code sample or steps: public class Utils {
private ConcurrentHashMap<String, TransferUtility> transferUtilityConcurrentHashMap = new ConcurrentHashMap<>();
private final Context context;
private final GsonHelper gsonHelper;
Utils(Context context, GsonHelper gsonHelper) {
this.context = context;
this.gsonHelper = gsonHelper;
}
public TransferUtility getTransferUtility(SessionModel sessionModel) {
TransferUtility sTransferUtility = transferUtilityConcurrentHashMap.get("12345");
if (sTransferUtility != null) {
return sTransferUtility;
} else {
return getNewTransferUtility(sessionModel);
}
}
private TransferUtility getNewTransferUtility(SessionModel sessionModel) {
AWSConfiguration awsConfiguration = getAWSConfiguration(sessionModel);
TransferUtility sTransferUtility = TransferUtility.builder()
.context(context)
.s3Client(getS3Client(sessionModel.getRegionName(),
awsConfiguration))
.awsConfiguration(awsConfiguration)
.build();
transferUtilityConcurrentHashMap.put("12345", sTransferUtility);
return sTransferUtility;
}
private AmazonS3Client getS3Client(String regionString, AWSConfiguration awsConfiguration) {
AmazonS3Client sS3Client = null;
try {
Region region = Region.getRegion(regionString);
sS3Client = new AmazonS3Client(getCredProvider( awsConfiguration), region);
} catch (Exception e) {
Log.e("error: ", e);
}
return sS3Client;
}
private AWSCredentialsProvider getCredProvider(AWSConfiguration awsConfiguration) {
AWSCredentialsProvider sMobileClient = null;
final CountDownLatch latch = new CountDownLatch(1);
AWSMobileClient.getInstance().initialize(context, awsConfiguration, new Callback<UserStateDetails>() {
@Override
public void onResult(UserStateDetails result) {
latch.countDown();
}
@Override
public void onError(Exception e) {
Log.e("error: ", e);
latch.countDown();
}
});
try {
latch.await();
sMobileClient = AWSMobileClient.getInstance();
} catch (InterruptedException e) {
Log.e("error: ", e);
}
return sMobileClient;
}
private AWSConfiguration getAWSConfiguration(SessionModel sessionModel) {
AWSConfig awsConfig = getAWSConfig(sessionModel);
JSONObject jsonObject = null;
String awsConfigString = gsonHelper.fromObjectToString(awsConfig);
try {
jsonObject = new JSONObject(awsConfigString);
} catch (JSONException e) {
Log.e("error" + e);
}
AWSConfiguration awsConfiguration = new AWSConfiguration(jsonObject);
setLogin(sessionModel, awsConfiguration);
return awsConfiguration;
}
private AWSConfig getAWSConfig(SessionModel sessionModel) {
IdentityDefault identityDefault = new IdentityDefault();
IdentityManager identityManager = new IdentityManager();
identityManager.setIdentityDefault(identityDefault);
CognitoDefault cognitoDefault = new CognitoDefault();
cognitoDefault.setPoolId(sessionModel.getIdentityPoolId());
cognitoDefault.setRegion(sessionModel.getRegionName());
CognitoIdentity cognitoIdentity = new CognitoIdentity();
cognitoIdentity.setCognitoDefault(cognitoDefault);
CredentialsProvider credentialsProvider = new CredentialsProvider();
credentialsProvider.setCognitoIdentity(cognitoIdentity);
S3Default s3Default = new S3Default();
s3Default.setBucket(sessionModel.getTempBucketName());
s3Default.setRegion(sessionModel.getRegionName());
S3TransferUtility s3TransferUtility = new S3TransferUtility();
s3TransferUtility.setS3Default(s3Default);
AWSConfig awsConfig = new AWSConfig();
awsConfig.setVersion("1.0");
awsConfig.setIdentityManager(identityManager);
awsConfig.setCredentialsProvider(credentialsProvider);
awsConfig.setS3TransferUtility(s3TransferUtility);
return awsConfig;
}
private void setLogin(SessionModel sessionModel) {
DeveloperAuthenticationProvider developerProvider = new DeveloperAuthenticationProvider(sessionModel);
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(context, developerProvider, sessionModel.getRegions());
HashMap<String, String> loginsMap = new HashMap<String, String>();
loginsMap.put(developerProvider.getProviderName(), developerProvider.getIdentityId());
credentialsProvider.setLogins(loginsMap);
credentialsProvider.refresh();
}
}
public class DeveloperAuthenticationProvider extends AWSAbstractCognitoDeveloperIdentityProvider {
private SessionModel sessionModel;
public DeveloperAuthenticationProvider(SessionModel sessionModel) {
super(null, sessionModel.getIdentityPoolId(), sessionModel.getRegions());
this.sessionModel = sessionModel;
}
@Override
public String getProviderName() {
return sessionModel.getDeveloperProviderName();
}
@Override
public String refresh() {
setToken(sessionModel.getToken());
update(getIdentityId(), sessionModel.getToken());
return sessionModel.getToken();
}
@Override
public String getIdentityId() {
return sessionModel.getIdentityId();
}
}
Which AWS service(s) are affected?
Expected behavior A clear and concise description of what you expected to happen. Assets should be uploaded successfully to S3
Screenshots If applicable, add screenshots to help explain your problem. NA
Environment Information (please complete the following information):
- AWS Android SDK Version: [e.g. 2.6.25]: 2.45.0
- Device: [e.g. Pixel XL, Simulator]: Samsung M52 5G (Others device as well)
- Android Version: [e.g. Nougat 7.1.2]: 11 (on Android 10 & other OS as well)
- Specific to simulators: [e.g. Yes/No]: No
Additional context Add any other context about the problem here.
@girishacme Logs are pointing to failure to refresh cognito token, could you please make sure your cognito setup is working as expected.
If yes, then please share your code for SessionModel and also post clear steps to repro this.
@sdhuka After receiving aws token from the server, on success token fetch:
public void onTokenFetch(boolean isSuccessFull, AWSToken awsToken, int errorCode) { if (isSuccessFull) { SessionModel sessionModel = new SessionModel(); sessionModel.setDeveloperProviderName(awsToken.getDeveloperProviderName()); sessionModel.setIdentityId(awsToken.getIdentityId()); sessionModel.setIdentityPoolId(awsToken.getIdentityPoolId()); sessionModel.setRegionName(awsToken.getRegionName()); sessionModel.setRegions(Regions.fromName(awsToken.getRegionName())); sessionModel.setTempBucketName(awsToken.getTempBucketName()); sessionModel.setToken(awsToken.getToken()); startUpload(); } else { handleFailure(errorCode); } }
private void startUpload() {
try {
File file = getFileToUpload(id);
if (file != null && file.exists()) {
transferUtility = awsUtils.getTransferUtility(customReplicationSession);
String key = getKey(id);
TransferObserver observer = transferUtility.upload(key, file);
id = observer.getId();
observer.setTransferListener(this);
} else {
handleFailure("File not exists");
}
} catch (Exception exception) {
Log.e("Error while uploading assets: " + exception);
}
}
Code to get transfer utility is already shared above.
This issues starts occurring any time, means there is no as such repro steps for this. Do let me know if you required anything else
@tylerjroach Any update on this?
Referencing this previous issue as it is related: https://github.com/aws-amplify/aws-sdk-android/issues/2807
This looks similar to the previous ticket that went unresolved. It appears that the issue could be a bug in Android Studio's Network inspector. The stacktrace posted shows:
com.android.tools.appinspection.network.httpurl.TrackedHttpURLConnection.getErrorStream(TrackedHttpURLConnection.kt:155)
TrackedHttpURLConnection does not exist in the SDK, and is injected by Android Studio's network profiler. Are these crashes only happening when the app is being debugged? If not, it would be helpful to see a crash report that does not lead to Android Studio's TrackedHttpURLConnection.
No, many times, I faced this issue when I am not debugging the app, Right now, I don't have any logs for that specific case, but I am sure I faced this issue when I was not debugging the app.
@girishacme Please follow up if you are able to produce a Stacktrace that does not com from com.android.tools.appinspection
. We should be able to track down the issue if a Stacktrace is provided that is not wrapped with the Network Inspector crash.
@tylerjroach I will share the logs once this is reproducible without com.android.tools.appinspection
We will re-open and investigate if we receive logs without appinspection.