Save Image to android local folder fails in some device - android-contentresolver

I'm saving images from bitmap to android local folder using below code,
val relativeLocation = Environment.DIRECTORY_PICTURES + "/" + "MyAppName"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "Filename")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation)
}
}
val resolver = reqireActivity().contentResolver
val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
uri?.let { uri ->
val stream = resolver.openOutputStream(uri)
stream?.let { stream ->
if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream)) {
throw IOException("Failed to save bitmap.")
}
} ?: throw IOException("Failed to get output stream.")
} ?: throw IOException("Failed to create new MediaStore record")
It works well in all devices, but now in crashlytics, i'm getting following error message from MI-Note4(android-7.0) and Mi Redmi 5Plus(android-8.1.0) devices,
Fatal Exception: java.lang.IllegalArgumentException
Unknown URL content://media/external/images/media
at android.content.ContentResolver.insert
Not sure really how to solve this issue

Related

Reading files from S3 using HadoopInputFile yields FileNotFoundException

I am trying to read parquet files from directory at S3
val bucketKey = "s3a://foo/direcoty_to_retrieve/"
val conf: Configuration = new Configuration()
conf.setBoolean(AvroReadSupport.AVRO_COMPATIBILITY, true)
val inputFile = HadoopInputFile.fromPath(new Path(bucketKey), conf)
val reader: ParquetReader[GenericRecord] = AvroParquetReader.builder[GenericRecord](inputFile).withConf(conf).build()
however I am getting
Exception in thread "main" java.io.FileNotFoundException: No such file or directory: s3a://foo/direcoty_to_retrieve
at org.apache.hadoop.fs.s3a.S3AFileSystem.s3GetFileStatus(S3AFileSystem.java:3356)
at org.apache.hadoop.fs.s3a.S3AFileSystem.innerGetFileStatus(S3AFileSystem.java:3185)
at org.apache.hadoop.fs.s3a.S3AFileSystem.getFileStatus(S3AFileSystem.java:3053)
at org.apache.parquet.hadoop.util.HadoopInputFile.fromPath(HadoopInputFile.java:39)
EDIT:
When I use the AvroParquetReader.builder with filePath e.g :
val reader: ParquetReader[GenericRecord] = AvroParquetReader.builder[GenericRecord](new Path(bucketKey)).withConf(conf).build()
it works, however this option is deprecated and I rather not use it.
on local directory it works. my env variables for AWS_ACCESS_KEY and AWS_SECRET_ACCESS_KEY are set correctly. what can be the problem ?
I faced the same issue with reading parquet file from Amazon S3 storage via Alpakka Avro parquet lib (which depends on parquet-hadoop-1.10.1.jar). After some debugging I found out the issue in ParquetReader.build method.
public ParquetReader<T> build() throws IOException {
ParquetReadOptions options = optionsBuilder.build();
if (path != null) {
FileSystem fs = path.getFileSystem(conf);
FileStatus stat = fs.getFileStatus(path);
if (stat.isFile()) {
return new ParquetReader<>(
Collections.singletonList((InputFile) HadoopInputFile.fromStatus(stat, conf)),
options,
getReadSupport());
} else {
List<InputFile> files = new ArrayList<>();
for (FileStatus fileStatus : fs.listStatus(path, HiddenFileFilter.INSTANCE)) {
files.add(HadoopInputFile.fromStatus(fileStatus, conf));
}
return new ParquetReader<T>(files, options, getReadSupport());
}
} else {
return new ParquetReader<>(Collections.singletonList(file), options, getReadSupport());
}
}
When HadoopInputFile is used as input, builder path property set to null and reader initiated in else block. As parquet file represented as a directory in filesystem this leads to java.io.FileNotFoundException.
Solution for now will be to use deprecated method:
AvroParquetReader.builder[GenericRecord](new Path(bucketKey)).withConf(conf).build()

MongoDB reactive template transactions

I've been using mongodb for my open source project for more than a year now and recently I decided to try out the transactions. After writing some tests for methods that use transactions I figured out that they throw some strange exceptions and I can't figure out what is the problem. So I have a method delete that uses custom coroutine context and a mutex:
open suspend fun delete(photoInfo: PhotoInfo): Boolean {
return withContext(coroutineContext) {
return#withContext mutex.withLock {
return#withLock deletePhotoInternalInTransaction(photoInfo)
}
}
}
It then calls a method that executes some deletion:
//FIXME: doesn't work in tests
//should be called from within locked mutex
private suspend fun deletePhotoInternalInTransaction(photoInfo: PhotoInfo): Boolean {
check(!photoInfo.isEmpty())
val transactionMono = template.inTransaction().execute { txTemplate ->
return#execute photoInfoDao.deleteById(photoInfo.photoId, txTemplate)
.flatMap { favouritedPhotoDao.deleteFavouriteByPhotoName(photoInfo.photoName, txTemplate) }
.flatMap { reportedPhotoDao.deleteReportByPhotoName(photoInfo.photoName, txTemplate) }
.flatMap { locationMapDao.deleteById(photoInfo.photoId, txTemplate) }
.flatMap { galleryPhotoDao.deleteByPhotoName(photoInfo.photoName, txTemplate) }
}.next()
return try {
transactionMono.awaitFirst()
true
} catch (error: Throwable) {
logger.error("Could not delete photo", error)
false
}
}
Here I have five operations that delete data from five different documents. Here is an example of one of the operations:
open fun deleteById(photoId: Long, template: ReactiveMongoOperations = reactiveTemplate): Mono<Boolean> {
val query = Query()
.addCriteria(Criteria.where(PhotoInfo.Mongo.Field.PHOTO_ID).`is`(photoId))
return template.remove(query, PhotoInfo::class.java)
.map { deletionResult -> deletionResult.wasAcknowledged() }
.doOnError { error -> logger.error("DB error", error) }
.onErrorReturn(false)
}
I want this operation to fail if either of deletions fails so I use a transaction.
Then I have some tests for a handler that uses this delete method:
#Test
fun `photo should not be uploaded if could not enqueue static map downloading request`() {
val webClient = getWebTestClient()
val userId = "1234235236"
val token = "fwerwe"
runBlocking {
Mockito.`when`(remoteAddressExtractorService.extractRemoteAddress(any())).thenReturn(ipAddress)
Mockito.`when`(banListRepository.isBanned(Mockito.anyString())).thenReturn(false)
Mockito.`when`(userInfoRepository.accountExists(userId)).thenReturn(true)
Mockito.`when`(userInfoRepository.getFirebaseToken(Mockito.anyString())).thenReturn(token)
Mockito.`when`(staticMapDownloaderService.enqueue(Mockito.anyLong())).thenReturn(false)
}
kotlin.run {
val packet = UploadPhotoPacket(33.4, 55.2, userId, true)
val multipartData = createTestMultipartFile(PHOTO1, packet)
val content = webClient
.post()
.uri("/v1/api/upload")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(multipartData))
.exchange()
.expectStatus().is5xxServerError
.expectBody()
val response = fromBodyContent<UploadPhotoResponse>(content)
assertEquals(ErrorCode.DatabaseError.value, response.errorCode)
assertEquals(0, findAllFiles().size)
runBlocking {
assertEquals(0, galleryPhotoDao.testFindAll().awaitFirst().size)
assertEquals(0, photoInfoDao.testFindAll().awaitFirst().size)
}
}
}
#Test
fun `photo should not be uploaded when resizeAndSavePhotos throws an exception`() {
val webClient = getWebTestClient()
val userId = "1234235236"
val token = "fwerwe"
runBlocking {
Mockito.`when`(remoteAddressExtractorService.extractRemoteAddress(any())).thenReturn(ipAddress)
Mockito.`when`(banListRepository.isBanned(Mockito.anyString())).thenReturn(false)
Mockito.`when`(userInfoRepository.accountExists(userId)).thenReturn(true)
Mockito.`when`(userInfoRepository.getFirebaseToken(Mockito.anyString())).thenReturn(token)
Mockito.`when`(staticMapDownloaderService.enqueue(Mockito.anyLong())).thenReturn(true)
Mockito.doThrow(IOException("BAM"))
.`when`(diskManipulationService).resizeAndSavePhotos(any(), any())
}
kotlin.run {
val packet = UploadPhotoPacket(33.4, 55.2, userId, true)
val multipartData = createTestMultipartFile(PHOTO1, packet)
val content = webClient
.post()
.uri("/v1/api/upload")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(multipartData))
.exchange()
.expectStatus().is5xxServerError
.expectBody()
val response = fromBodyContent<UploadPhotoResponse>(content)
assertEquals(ErrorCode.ServerResizeError.value, response.errorCode)
assertEquals(0, findAllFiles().size)
runBlocking {
assertEquals(0, galleryPhotoDao.testFindAll().awaitFirst().size)
assertEquals(0, photoInfoDao.testFindAll().awaitFirst().size)
}
}
}
#Test
fun `photo should not be uploaded when copyDataBuffersToFile throws an exception`() {
val webClient = getWebTestClient()
val userId = "1234235236"
val token = "fwerwe"
runBlocking {
Mockito.`when`(remoteAddressExtractorService.extractRemoteAddress(any())).thenReturn(ipAddress)
Mockito.`when`(banListRepository.isBanned(Mockito.anyString())).thenReturn(false)
Mockito.`when`(userInfoRepository.accountExists(userId)).thenReturn(true)
Mockito.`when`(userInfoRepository.getFirebaseToken(Mockito.anyString())).thenReturn(token)
Mockito.`when`(staticMapDownloaderService.enqueue(Mockito.anyLong())).thenReturn(true)
Mockito.doThrow(IOException("BAM"))
.`when`(diskManipulationService).copyDataBuffersToFile(Mockito.anyList(), any())
}
kotlin.run {
val packet = UploadPhotoPacket(33.4, 55.2, userId, true)
val multipartData = createTestMultipartFile(PHOTO1, packet)
val content = webClient
.post()
.uri("/v1/api/upload")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(multipartData))
.exchange()
.expectStatus().is5xxServerError
.expectBody()
val response = fromBodyContent<UploadPhotoResponse>(content)
assertEquals(ErrorCode.ServerDiskError.value, response.errorCode)
assertEquals(0, findAllFiles().size)
runBlocking {
assertEquals(0, galleryPhotoDao.testFindAll().awaitFirst().size)
assertEquals(0, photoInfoDao.testFindAll().awaitFirst().size)
}
}
}
Usually the first test passes:
and the following two fail with the following exception:
17:09:01.228 [Thread-17] ERROR com.kirakishou.photoexchange.database.dao.PhotoInfoDao - DB error
org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 24 (LockTimeout): 'Unable to acquire lock '{8368122972467948263: Database, 1450593944826866407}' within a max lock request timeout of '5ms' milliseconds.' on server 192.168.99.100:27017.
And then:
Caused by: com.mongodb.MongoCommandException: Command failed with error 246 (SnapshotUnavailable): 'Unable to read from a snapshot due to pending collection catalog changes; please retry the operation. Snapshot timestamp is Timestamp(1545661357, 23). Collection minimum is Timestamp(1545661357, 24)' on server 192.168.99.100:27017.
And:
17:22:36.951 [Thread-16] WARN reactor.core.publisher.FluxUsingWhen - Async resource cleanup failed after cancel
com.mongodb.MongoCommandException: Command failed with error 251 (NoSuchTransaction): 'Transaction 1 has been aborted.' on server 192.168.99.100:27017.
Sometimes two of them pass and the last one fails.
It looks like only the first transaction succeeds and any following will fail and I guess the reason is that I have to manually close it (or the ClientSession). But I can't find any info on how to close transactions/sessions. Here is one of the few examples I could find where they use transactions with reactive template and I don't see them doing anything additional to close transaction/session.
Or maybe it's because I'm mocking a method to throw an exception inside the transaction? Maybe it's not being closed in this case?
The client sessions/tranactions are closed properly however it appears the indexes creation in tests are acquiring global lock causes the next transaction lock to fall behind and wait before timing out on the lock request.
Basically you have to manage your index creation so they don’t interfere with transaction from client.
One quick fix would be to increase the lock timeout by running below command in shell.
db.adminCommand( { setParameter: 1, maxTransactionLockRequestTimeoutMillis: 50 } )
In production you can look at the transaction error label
and retry the operation.
More here https://docs.mongodb.com/manual/core/transactions-production-consideration/#pending-ddl-operations-and-transactions
You could check connection options and accord you driver
val connection = MongoConnection(List("localhost"))
val db = connection.database("plugin")
...
connection.askClose()
you could search method askClose(), hope you can helpfull

Matching a String in a text file, and return back the meaning of the word in the client part (Scala)

I would like to solve a problem where the client will send a word to the server, and server will run through the text file and return the meaning of the word that is typed by the user. My problem is when a matching word is typed, i will return the match word meaning, at the same time return back other "Word not found" (which is my control statement). So i would like to just return the meaning of the word only if the word is matched and found
Heres my code:
Server part
Future {
//store local socket references for processing
val client = socket
try {
// Get a communication stream associated with the socket
val is = new BufferedReader(new InputStreamReader(client.getInputStream))
// Get a communication stream associated with the socket
val os = new PrintStream(client.getOutputStream)
val inFile = new File(filename)
val readFile = new Scanner(inFile)
var input : String = null;
while (true) {
// Read from input stream
var line: String = is.readLine() // read the word from client
println("The client send " + line)
while (readFile.hasNext()) {
input = readFile.nextLine()
println("From the file " + input)
if (input.contains(line)) {
os.println(input)
os.flush()
}
else{
os.println("Word not found")
}
}
}
} catch {
case e: Exception => e.printStackTrace
} finally {
// Close the connection, but not the server socket
client.close()
}
}
Client Part
val is = new BufferedReader(new InputStreamReader(client.get.getInputStream))
val os = new PrintStream(client.get.getOutputStream) // write to server a strin
println("Please Input Ur word ")
val user = readLine
os.println(user)
while (true) {
var line: String = is.readLine() //receive string from server
println(line)
}
My text file is formatted this way:
super-very good or pleasant; excellent.
Use the following approach:
var found = false;
while (readFile.hasNext() && !found) {
input = readFile.nextLine()
println("From the file " + input)
if (input.contains(line)) {
os.println(input)
os.flush()
found = true;
}
}
if(!found) {
os.println("Word not found")
os.flush()
}
There are much more beautiful ways to do this, but as you seem to be a beginner, this is the simplest solution possible.
If you are interested in a functional approach, I will gladly help.
Hope this helps.

Update wsdl definition and requests programmatically and keep parameters/properties in SoapUI

We have a lot of wsdls and it's pretty annoying to update/refactor/update definitions and requests in my SoapUI project so I started to work a bit on groovy script for this. Curreny it look like this:
import com.eviware.soapui.impl.wsdl.*
import com.eviware.soapui.model.iface.Interface
import org.apache.log4j.Logger
import TestHelper.Wsdl.*
import static com.eviware.soapui.impl.wsdl.actions.iface.UpdateInterfaceAction.recreateRequests
import static com.eviware.soapui.impl.wsdl.actions.iface.UpdateInterfaceAction.recreateTestRequests
class UpdateWsdls {
WsdlProjectPro wsdlProject
Logger log
public UpdateWsdls(Logger log, String projectFileName) {
this.log = log
this.wsdlProject = new WsdlProjectPro(projectFileName)
}
void updateInterfaceDefinitions(List<WsdlInfo> wsdlInfos) {
if(!wsdlProject.isOpen()) {
log.warn "Failed to open project"
return
}
wsdlInfos.each { wsdlInfo ->
def interfaceNames = getBindingNames(wsdlInfo.path)
interfaceNames.each {
updateInterfaceDefinition(it, wsdlInfo)
}
}
}
void updateInterfaceDefinition(String interfaceName, WsdlInfo wsdlInfo) {
List<Interface> interfacesList = wsdlProject.interfaceList
interfacesList.each { Interface anInterface ->
if (anInterface instanceof WsdlInterface && interfaceName.equals(anInterface.name)) {
WsdlInterface wsdlInterface = (WsdlInterface) anInterface
def currentVersion = -1
def text = wsdlInterface.getBindingName().toString().split('}');
if(text.size() > 0) {
currentVersion = WsdlHelper.getVersionNumber(text[0])
}
if(currentVersion < wsdlInfo.version) {
log.info "Updating ${interfaceName}, ${currentVersion} -> ${wsdlInfo.version}"
wsdlInterface.updateDefinition(wsdlInfo.path, false)
updateRequests(wsdlInterface)
} else {
log.info "${interfaceName} already up-to-date with version ${currentVersion}"
}
}
}
}
void updateRequestDo(WsdlInterface wsdlInterface) {
try {
recreateRequests(wsdlInterface,false,false,true,false)
}
catch(Exception ex) {
log.warn "Failed to update request ${wsdlInterface.getBindingName()}"
}
try {
recreateTestRequests(wsdlInterface,false,false,true,false)
} catch(Exception ex) {
log.warn "Failed to update test request ${wsdlInterface.getBindingName()}"
}
}
void saveWsdlProject() {
wsdlProject.save()
wsdlProject.release()
}
def getBindingNames(String wsdlFile) {
def definitions = new XmlParser().parse(new File(wsdlFile))
return definitions.getByName('*:binding').#name
}
}
def projectPath = ".."
//Path to directory with the latest wsdls
def wsdlPathRoot = ".."
def w = new WsdlHelper(log)
//Get info (name, path, verison number) of the latest wsdls
def wsdlInfos = w.getLatestWsdlInfo(wsdlPathRoot)
UpdateWsdls updateWsdl = new UpdateWsdls(log, projectPath)
log.info "Updating definitions"
updateWsdl.updateInterfaceDefinitions(wsdlInfos)
log.info "Saving project"
updateWsdl.saveWsdlProject()
log.info "Restart SoapUI for changes to take effect"
In summary it do this:
Walk trough the directory at wsdlPathRoot for all wsdls and pick out those with the latest version.
Loop through our current interfaces and check if we have the latest version.
If not, update it's definition with the new path and recreate requests and test requests.
This works fine so far, the problem is that all my data/properties in all my requests/tests are gone. This is a pretty big deal as many of our requests take 10+ parameters and it would take a long time to insert them manually again.
I know soapui pro have a function that is called "refactor definition" and it manage to put everything back after an update. Is it possible to use/call on this programmatically?

Spray rejection handler not detecting an existing path

I have a file static.scala :
val staticRoute = {
path("") {
getFromResource("web/index.html")
} ~ pathPrefix("web") {
getFromResourceDirectory("web")
}
}
Another file a.scala :
val actionRoute = (handleRejections(rejectionHandler) & handleExceptions(exceptionHandler))
{
path("action" / "create") {
(put | post) {
implicit ctx => {
val xmlString = ctx.request.entity.asString
val actionObject = XML.loadString(xmlString).toAction
ActionService.write(actionObject)
sendResponse(StatusCodes.OK, APIResponseOK(Map("id" -> actionObject.id)))
}
}
}
}
My Base.scala contains the definition of the rejectionHandler :
val rejectionHandler = RejectionHandler {
case Nil => ctx => {
complete((StatusCodes.NotFound, "The Requested Resource was not found"))
}
case mcr : MissingCookieRejection =>ctx=> { //testing
complete(StatusCodes.BadRequest, "Missing cookie")
}
}
Both the files extend Base.scala which has the rejection handler defined in it. However on opening the correct port for the server ( localhost:8080 ) which corresponds to
path("")
in static.scala , the rejectionHandler still is going to case Nil and printing the message "The Requested Resource was not found" which should not be the case! Shouldn't it enter the handler if that path is not defined? If i comment out the rejectionHandler everything works as expected. Please help me out !
actionRoute will complete / because it doesn't have a path for it and does have a handleRejections. Which means it does have a route for / and actionRoute ~ staticRoute will never "fall through" to staticRoute.
You usually want to only do rejection handling at the very top level (or maybe within a pathPrefix, if you don't want other routes to use the same prefix). Move the handleRejections out of actionRoute and move it right up to the top level:
handleRejections(myHandler) {
actionsRoute ~ staticRoute
}