Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

kitten smoothie posted:

Oh, and don't forget that the patch didn't fully patch the problem.

I'm really curious how many full time Android developers carry iPhones as their personal device, because we have a bigger window into the sausage factory.

I actually have both a personal iPhone and a work Android phone. The iPhone has never quietly crashed in my pocket, unlike my Nexus 6, and the battery life is simply superior. The Android phone has fewer restrictions and let me do really fun and neat stuff, but at a price of letting everyone under the sun gently caress things up.

Adbot
ADBOT LOVES YOU

fritz
Jul 26, 2003

Subjunctive posted:

Better than "Patch November", yeah.

On the Usenet calendar.

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

I have a question that might not be android specific, but I'm eager to get your views.

I am implementing asymmetrical encryption for an app. It uses AES to encrypt a file, using a randomly generated password. This password is then written to a file and RSA encrypted using a public key.

Now, when setting up the Cipher for RSA encryption, we use this call:

code:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Now, my understanding is that ECB is a no-no, because it is insecure. In fact Android Studio explicitly has a warning just for that issue. However, my understanding is that in the case of RSA it doesn't matter because RSA doesn't employ block-chaining (and as a result the ECB specified in that call is basically ignored). For AES we use AESCrypt which uses CBC by default.

Is my understanding on this issue correct? I draw my understanding from, among other places, here:

http://armoredbarista.blogspot.co.uk/2012/09/rsaecb-how-block-operation-modes-and.html

and that other encryption libraries such as BouncyCastle, actually ignore the operation mode for RSA.

Doctor w-rw-rw-
Jun 24, 2008
My understanding jives with yours that RSA isn't intended to be used as a block cipher and ECB sucks. I haven't used them together, although my slightly-informed guess would also be that it doesn't matter because ECB is ignored.

Given that Android uses a cut-down BouncyCastle for its crypto (link), I'd say that if you've looked at BouncyCastle and found that it ignored the operation mode, chances are very good you'll see the same behavior on the standard Android platform

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

Doctor w-rw-rw- posted:

My understanding jives with yours that RSA isn't intended to be used as a block cipher and ECB sucks. I haven't used them together, although my slightly-informed guess would also be that it doesn't matter because ECB is ignored.

Given that Android uses a cut-down BouncyCastle for its crypto (link), I'd say that if you've looked at BouncyCastle and found that it ignored the operation mode, chances are very good you'll see the same behavior on the standard Android platform

Thanks for the input, its seems this is the case.

I have another question though. I recently updated my SDK and now when building I'm getting weird errors:
code:
/Users/picroft/Development/AndroidProjects/MyApp/app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.0/res/values-v23/values-v23.xml
Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
The file in question is inside the generated folder, so its pointing to errors in the code that Android studio is creating when building.

I've been told elsewhere that I can update my target SDK version to 23, but I don't want to do this just now as it causes chaos throughout the app, specifically our tools library which uses org.apache.http packages, many of which appear to have been surgically excised at some point. I just want it to go back to its previous behaviour for now. Does anyone know how to get around this/stop it from complaining?

Tunga
May 7, 2004

Grimey Drawer
What is your minimum SDK to set?

When you say you updated your SDK, what exactly did you update? Build tools? Try reverting that to 22.0.1. That shouldn't matter but there might be a bug. I haven't had any issues here with an app that targets 21.

Edit: There are some Google results for this from the last couple of days, it looks like AS is switching to appcompat:23.0.0 by itself. Try reverting that to 22.2.1.

Tunga fucked around with this message at 11:21 on Aug 19, 2015

kitten smoothie
Dec 29, 2001

https://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client

They broke the httpclient stuff out into legacy lib so that's an option too. Not to say I'd rely on this past M though. But that might be able to get you compiling against 23 without issues from that.

And yes, your compile SDK must match the Android release level specified in the support/appcompat library versions.

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

Thanks guys, I got the issue sorted in the end.

I do have another question regarding the rotation vector sensor. I understand that the old orientation sensor is deprecated and shouldn't be used going forward, so I'm experimenting with the Sensor.TYPE_ROTATION_VECTOR which I understand gives a quaternion representation of the device orientation through sensor fusion (i.e. combining sensor data from various hardware sensors, such as gyroscope, accelerometer etc. to give a more accurate reading).

I've tested this on a couple of devices to convert the raw event data into yaw, pitch and roll values:

code:
 // Convert the rotation-vector to a 4x4 matrix.
        SensorManager.getRotationMatrixFromVector(mRotationMatrixFromVector, event.values);
        SensorManager.remapCoordinateSystem(mRotationMatrixFromVector,
                SensorManager.AXIS_X, SensorManager.AXIS_Z,
                mRotationMatrix);
        SensorManager.getOrientation(mRotationMatrix, orientationVals);

        // Optionally convert the result from radians to degrees
        orientationVals[0] = (float) Math.toDegrees(orientationVals[0]);
        orientationVals[1] = (float) Math.toDegrees(orientationVals[1]);
        orientationVals[2] = (float) Math.toDegrees(orientationVals[2]);

        tv1.setText("Yaw:" + orientationVals[0]);
        tv2.setText("Pitch:" + orientationVals[1]);
        tv3.setText("Roll:" + orientationVals[2]);
On a Samsung Galaxy S3 mini, this results in a severe lag when updating the values, especially pitch. By lag, I mean the results returned from the onSensorChanged() lag up to 5-6 seconds behind the actual device orientation. Testing on another device (the Note 3) results in much smoother and less laggy sensor values.

My question is, is this lagginess a result of hardware issues? I would imagine the S3 mini is less powerful than the Note 3, but if its simply down to hardware, that would explain it. My google searches so far haven't turned up much regarding lag.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

It might be something to do with the Note 3 having a hardware gyroscope, and the Mini lacking it (don't actually know if that's true), but obviously 5 seconds is a bit excessive.

It might be worth running getReportingMode() when you get the sensor, and check they're both continuous types, and maybe try different update speeds when you register the event listener. The rotation vector is a fused sensor so it's a black box with its own filtering going on, which could be slow as anything internally

You could try getting the data yourself, like this:
http://stackoverflow.com/a/10291428

It'll be noisier and possibly less accurate, but at least you can see if the delay is in the sensor fusion

hooah
Feb 6, 2006
WTF?
I'm trying to add TTS to my 5-second countdown timer:
Java code:
@Override
public void onInit(int status){
    if(status == TextToSpeech.SUCCESS){
        // Make the countdown timer
        mCountdownView = (TextView) findViewById(R.id.countdown);
        new CountDownTimer(5000, 100){
            public void onTick(long millisUntilFinished){
                long time = (millisUntilFinished / 1000) + 1;
                mCountdownView.setText("seconds remaining: " + time);
                mTts.speak(String.valueOf(time), TextToSpeech.QUEUE_ADD, null);
            }

            public void onFinish(){
                mCountdownView.setText("start!");
                mTts.speak("start!", TextToSpeech.QUEUE_ADD, null);
                // post the updating task so it will fire - giving it the usual 100ms delay here
                mDataHandler.postDelayed(updateFile, UPDATE_DELAY);
            }
        }.start();
    }
}
However, the voice doesn't start speaking until ~3 seconds left, and repeats each integer many times, for far longer than the remaining time. I tried surrounding the call to speak with an if like if(millisUntilFinished % 1000 == 0), but that causes the voice to only speak "start". I've done some reading and it seems that you don't get millisecond resolution, so millisUntilFinished might never be a round thousand. What else can I try?

Tunga
May 7, 2004

Grimey Drawer

hooah posted:

What else can I try?
When you recalculate the value for time, check if it's different to the previous value, and only read it out if it is.

Edit: And make time a member variable, obviously.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

You're setting your tick to 100ms, so it's going to update you 50 times in 5 seconds (or it's going to try!) Any reason you're firing it so often? If you just want to say and print 'X seconds left' in a normal countdown, and then start your scheduled task when you hit zero, you can just set your countdown interval in the constructor to 1000

hooah
Feb 6, 2006
WTF?

baka kaba posted:

You're setting your tick to 100ms, so it's going to update you 50 times in 5 seconds (or it's going to try!) Any reason you're firing it so often? If you just want to say and print 'X seconds left' in a normal countdown, and then start your scheduled task when you hit zero, you can just set your countdown interval in the constructor to 1000

Hmm. I tried this method, but "1" never gets displayed or spoken. I threw in some log statements to print out the value of millisUntilFinished, and got 4976, 3976, 4976, and 1977. I'll try out Tunga's method.

Edit: that works better. However, the first time the app is run, the speaking is still delayed. I thought my check on the status is supposed to prevent the counter from being initialized before the TTS engine is ready?

hooah fucked around with this message at 18:01 on Aug 25, 2015

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Well you're always adding 1 to your seconds remaining, and the CountDown timer doc says that onTick() is "fired on regular interval", and onFinish() is "fired when the time is up", so I'm guessing when the time left is zero it jumps straight to onFinish, so onTick never gets to output "1" (0+1)

You shouldn't need to actually check the millis for what you're doing. I mean I've never used this, but I'm assuming the idea is it you set it to fire every so often, and then it triggers arouuuuund about that time, which should be close enough. The millisUntilFinished parameter is there in case you need to know precisely how long is left, but if you're just going "5-4-3-2-1-go!" then you probably don't care

As far as the timing goes, at a guess the TTS engine is a bit slow. I've never really used it, but whenever I've heard it I never got the impression it was super responsive. You might be able to pre-buffer some speech somehow, maybe use QUEUE_FLUSH to force it to start saying the next number immediately (might cut off some delaying silence at the end)

e- I don't know if this will help, but you might be able to query the speech engines you find and check the voices they offer:
https://developer.android.com/reference/android/speech/tts/Voice.html
There are a bunch of latency constants, maybe you're getting one with a high latency

e2- this is a total hack, but try sending something like silence to the TTS engine at the start of method - maybe it needs some time to negotiate access to the audio stream or something, and needs time to warm up when you first use it, so give it a kick

baka kaba fucked around with this message at 18:47 on Aug 25, 2015

hooah
Feb 6, 2006
WTF?
Thanks, that let me clean up the code a lot, so now I just have
Java code:
@Override
public void onInit(int status){
    if(status == TextToSpeech.SUCCESS){
        // Make the countdown timer
        mCountdownView = (TextView) findViewById(R.id.countdown);
        new CountDownTimer(5000, 1000){
            public void onTick(long millisUntilFinished){
                mCountdownView.setText("seconds remaining: " + mTime);
                mTts.speak(String.valueOf(mTime), TextToSpeech.QUEUE_ADD, null);
                mTime--;
            }

            public void onFinish(){
                mCountdownView.setText("start!");
                mTts.speak("start!", TextToSpeech.QUEUE_ADD, null);
                // post the updating task so it will fire - giving it the usual 100ms delay here
                mDataHandler.postDelayed(updateFile, UPDATE_DELAY);
            }
        }.start();
    }
}
This still skips 1, both in displaying and in speech, but I was able to fudge that by increasing the initialization value of the CountdownTimer.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Well think about it this way - you're setting a timer that's 5 seconds long, and it ticks every second. So your first tick is going to occur at 4 seconds remaining (you wouldn't expect one as soon as you start it), and if you're starting your count at '5 seconds left' then you're always going to be out by one

What I'd do is make a little sayTime(int seconds) method that does all your printing/TTSing, call that from within your countdown tick callback, and also call it just before/after you start the timer. So you'll get an immediate update, and then one every tick, and you can set your initial counter to 5 like you'd expect. You can decrement it in the sayTime method (which might be better) or just do sayTime(seconds--) whenever you call it, or whatever you like

Personally I'd use a constant for the initial seconds, and make your timer length 1000 * that constant, so you only have to change it in one place if you ever feel like it, but that's another story!

e- my bad, I just looked at the source and it looks like a tick should fire almost immediately, so I'm not sure what's up with that!

baka kaba fucked around with this message at 19:25 on Aug 25, 2015

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

This is more to do with Android Studio than android itself, but this is doing my head in:

I have a project I'm trying to set up for instrumentation tests in Android Studio. I have it set up such that I can run instrumentation tests for the apps 2 flavours directly from Android Studio.

However, by running it in the command line through Gradle, I can generate a html report that is both useful visually to see a rundown of the test results, we also need such a report for documentation purposes.

Any time I try and run the instrumentation tests via 'gradle connectedCheck' in Android Studio's terminal, it always fails, with:

Execution failed for task ':app:mergeDevelopmentDebugAndroidTestJavaResources'.

Cannot determine expansion folder for /Users/picroft/Development/AndroidProjects/OurApp/app/build/intermediates/packagedJarsJavaResources/androidTest/development/debug/junit-4.12.jar936209038/LICENSE-junit.txt with folders


I have another app, a test one set up specifically to experiment with and practice setting up instrumentation tests and it works perfectly through Android studio and command line.

Both projects have 2 flavours and from I can see there aren't any meaningful differences in their gradle build files, but here they are for reference:

code:
buildscript {
    repositories {
        maven { url 'http://download.crashlytics.com/maven' }
    }

    dependencies {
        classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
    }
}
apply plugin: 'com.android.application'
apply plugin: 'crashlytics'

repositories {
    maven { url 'http://download.crashlytics.com/maven' }
}

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        applicationId "com.app.ourapp"
        minSdkVersion 16
        versionCode 11
        versionName "1.1"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            assets.srcDirs = ['src/main/assets',
                              'src/main/assets/font']
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }

    productFlavors {
        live {
            versionName "1.1 live"
            applicationId "com.app.ourapp.live"
        }
        development {
            versionName '1.1 development'
            applicationId "com.app.ourapp.development"
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile project(':library:datetimepicker')
    compile project(':library:tools')
    compile 'com.android.support:appcompat-v7:+'
    compile 'com.android.support:support-v4:+'
    compile 'com.crashlytics.android:crashlytics:1.+'
    compile 'org.quanqi:mpandroidchart:1.7.+'
    compile 'commons-io:commons-io:2.+'
    compile 'joda-time:joda-time:2.+'
    compile 'com.microsoft.azure.android:azure-storage-android:0.4.+'

    testCompile 'junit:junit:4.12'
    testCompile "org.robolectric:robolectric:${robolectricVersion}"
    testCompile "org.mockito:mockito-core:1.+"

    androidTestCompile 'junit:junit:4.12'
    androidTestCompile "org.mockito:mockito-core:1.+"
}
test app:

code:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.test.picroft.instrumentationtestapp"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
        newFlavour {
            applicationId "com.test.picroft.instrumentationtestapp.newflavor"
        }

        oldFlavour {
            applicationId "com.test.picroft.instrumentationtestapp.oldflavor"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.1'

    testCompile 'junit:junit:4.12'
    testCompile "org.mockito:mockito-core:1.+"

    androidTestCompile 'junit:junit:4.12'
    androidTestCompile "org.mockito:mockito-core:1.+"
}
Does anyone have any ideas where I'm going wrong?

hooah
Feb 6, 2006
WTF?
Evidently some users are inadvertently putting the phone to sleep while trying to record a motion. I read about using a wake lock, but putting the simple example in the PowerManager documentation in my activity that collects the data (and moving initialization code to onCreate and the lock release to onPause) didn't seem to work quite right - data is still being recorded with the screen off, but aside from the system time, it's all the same for that duration. That is, none of the values being recorded change until the screen comes back on again. Does this mean the motion sensors are going to sleep, or what?

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

I don't know what you're doing exactly, but if you're still using the code I wrote, it explicitly deregisters the sensors in onPause so they're only running while your app is visible. I probably stuck it in a sleep() call or something, so see if you have that and if you can put it somewhere more useful


PiCroft posted:


Does anyone have any ideas where I'm going wrong?

I really don't, Gradle is still the dark corner I don't go into unless I have to, but looking at the source you're getting that error from getExpansionFolder().
It's meant to append packagedJarsJavaResourcesFolder and sourceJavaResourcesFolder at the end of that error message, but it looks like they're both null for some reason. That probably doesn't help, but I figured I'd mention it just in case it's the clue you need to crack this whole case :shobon:

hooah
Feb 6, 2006
WTF?

baka kaba posted:

I don't know what you're doing exactly, but if you're still using the code I wrote, it explicitly deregisters the sensors in onPause so they're only running while your app is visible. I probably stuck it in a sleep() call or something, so see if you have that and if you can put it somewhere more useful

Oh, good grief, of course.

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

baka kaba posted:

I really don't, Gradle is still the dark corner I don't go into unless I have to, but looking at the source you're getting that error from getExpansionFolder().
It's meant to append packagedJarsJavaResourcesFolder and sourceJavaResourcesFolder at the end of that error message, but it looks like they're both null for some reason. That probably doesn't help, but I figured I'd mention it just in case it's the clue you need to crack this whole case :shobon:
Thanks for trying, as it turns out, it fixed itself for no apparent reason. Probably a clean and/or invalidate caches followed by reboots has sorted something out along the way.

I love gradle, it has so much power and a ton of stuff I like, but if something goes wrong, it can go badly wrong.

Super Dude
Jan 23, 2005
Do the Jew
I'm trying to save the content of a view into an image file, and have it show up in the gallery. The image is saving fine, but it never shows in the gallery app (Moto X) or Photos app. I can view the image just fine if I browse to it with a file explorer. Do I need to do something specific to tell the phone to add my directory to the gallery?

code:
 
dv.setDrawingCacheEnabled(true);
Bitmap bitmap = dv.getDrawingCache();

File imageRoot = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");
if(!imageRoot.exists())
	imageRoot.mkdirs();
File f = new File(imageRoot, "MyPic.jpg");
 try {
	FileOutputStream stream = new FileOutputStream(f);
	bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
	Toast.makeText(getApplicationContext(), "Image saved!", Toast.LENGTH_LONG).show();
	stream.flush();
	stream.close();
} catch (Exception e) {
	Log.e(TAG, "E: " + e.getMessage());
}

fins
May 31, 2011

Floss Finder

Super Dude posted:

I'm trying to save the content of a view into an image file, and have it show up in the gallery. The image is saving fine, but it never shows in the gallery app (Moto X) or Photos app. I can view the image just fine if I browse to it with a file explorer. Do I need to do something specific to tell the phone to add my directory to the gallery?


Rather than writing files directly, you can use the MediaStore.
i.e.
code:
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);

Super Dude
Jan 23, 2005
Do the Jew

fins posted:

Rather than writing files directly, you can use the MediaStore.
i.e.
code:
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);

Two issues:

1) This saved it to my camera folder, how do I get it to save to an app-specific folder? When I save pictures from other apps, they get put into a folder named after the app.
2) The image is saved it at the bottom of my pictures rather than the top, where the most recent images are. The date on the image is listed as Dec 31, 1969 at 7pm...

Any way to solve either of those?

Edit: Nevermind, I figured it out.

Super Dude fucked around with this message at 23:58 on Sep 4, 2015

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

PiCroft posted:

Thanks for trying, as it turns out, it fixed itself for no apparent reason. Probably a clean and/or invalidate caches followed by reboots has sorted something out along the way.

I love gradle, it has so much power and a ton of stuff I like, but if something goes wrong, it can go badly wrong.

Yeah I've not really looked into it yet, so for me it's mostly 'that thing that breaks in strange ways'. Seems like invalidating and cleaning is usually the way to go, huh? Helped me with my adventures in 'I don't recognise this so-called Fragment class' hell


Super Dude posted:

I'm trying to save the content of a view into an image file, and have it show up in the gallery. The image is saving fine, but it never shows in the gallery app (Moto X) or Photos app. I can view the image just fine if I browse to it with a file explorer. Do I need to do something specific to tell the phone to add my directory to the gallery?

You probably just need to tell MediaScanner to scan it (there's a more useful utility call above that one, breaks the link though). The gallery relies on the system's media database to tell it what stuff is on the phone, and give it access, so apps can just go through MediaStore instead of worrying about where all this stuff is. MediaStore will scan automatically (every reboot, not sure how often otherwise) but if apps want stuff added immediately, they have to explicitly request it

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
That said, the media scanner may automatically scan things you don't want included, hence the requirement of adding a .nomedia file to directories with content that shouldn't get scanned.

Farchanter
Jun 15, 2008
I'm having some performance issues using Canvas.drawBitmap() in a game I'm working on.

In each frame of animation, I'm drawing a background image the size of the screen using Canvas.drawBitmap(Bitmap, Rect src, Rect rest, Paint) and one out of every hundred frames or so is taking longer than the 1/30 of a second I have allotted for it, which doesn't happen when I just paint the screen with white instead of draw the Bitmap.

Some cursory Googling tells me that a Bitmap scaling during that particular draw method is a significant performance hit, but I'm having a hard time using Bitmap.createScaleBitmap() and getting the results I want, and I think I may be implementing incorrectly. I can post some source if that would be helpful, but I have some more general questions:

1) is there a way to force a Canvas to *not* scale an image, so I can visually confirm if something is working?
2) is drawing a screen-sized Bitmap every frame an optimal way to do this?

Thank you so much in advance!

hooah
Feb 6, 2006
WTF?
Is there a way to debug an app on a phone far away from me that's better than having the user install Android Studio and using TeamViewer to remote in to their machine?

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Farchanter posted:

I'm having some performance issues using Canvas.drawBitmap() in a game I'm working on.

In each frame of animation, I'm drawing a background image the size of the screen using Canvas.drawBitmap(Bitmap, Rect src, Rect rest, Paint) and one out of every hundred frames or so is taking longer than the 1/30 of a second I have allotted for it, which doesn't happen when I just paint the screen with white instead of draw the Bitmap.

Some cursory Googling tells me that a Bitmap scaling during that particular draw method is a significant performance hit, but I'm having a hard time using Bitmap.createScaleBitmap() and getting the results I want, and I think I may be implementing incorrectly. I can post some source if that would be helpful, but I have some more general questions:

1) is there a way to force a Canvas to *not* scale an image, so I can visually confirm if something is working?
2) is drawing a screen-sized Bitmap every frame an optimal way to do this?

Thank you so much in advance!

You could try using the same Rect for src and dst, to avoid scaling - so it'll either fill the canvas with part of the bitmap or draw the whole bitmap on part of the canvas, depending on which is bigger. The drawBitmap(Bitmap bitmap, float left, float top, Paint paint) method might not scale, give that one a try too.

But you might want to try getting the width and height of your canvas at the beginning, use Bitmap.createScaledBitmap to make a pre-scaled copy, and then pass that into the drawBitmap method I just mentioned. More memory use but you're offsetting some of the work.

Honestly though, if nobody in here has any tips you might want to ask in the game programming thread (we still have one of those, right?). In my experience Canvas was very slow when drawing full screen, too many elements and it started to chug - they've probably improved things since then, and there are probably optimisation tips I wasn't aware of, but some people in that thread might have more specific experience.

Also for this kind of thing it's worth doing some profiling to see exactly what's up and why you're dropping frames
http://developer.android.com/tools/debugging/debugging-tracing.html
http://android-developers.blogspot.co.uk/2010/10/traceview-war-story.html
Android Studio has a tool like this but I don't like it, it's harder for me to tell what's going on - you can open DDMS though and get to it from there. You might find that your drawing calls are just fine and something else is happening, like garbage collection. You can also open the cool new Memory and CPU tabs in Android Studio, and see if there's a blip whenever you see a bit of jank. That's more of a quick and dirty method, but you'll see pretty quickly if something's out of the ordinary or if you have a memory use/GC issue

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

hooah posted:

Is there a way to debug an app on a phone far away from me that's better than having the user install Android Studio and using TeamViewer to remote in to their machine?

If the user is technical, you can have them enable wifi debugging and then ssh tunnel your adb connection to their host machine, but I feel like the number of users who could handle that and couldn't just follow instructions themselves to run adb bugreport > bugreport.txt is pretty tiny.

hooah
Feb 6, 2006
WTF?
I did have them send a bug report from the settings menu, but my app shows up on logcat like three times, so that's not too helpful (assuming the person installed the verbose version). This'll be fun!

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

I have a quick question on the Android Location framework - I notice it has a getTime() method.

When testing, I noticed that if I set the device clock forward 6 hours and waited for a location update, the system time reported my current time +6 hours (unsurprisingly) but the location time reported my current, correct time.

My question is, where does the getTime() come from? Does it come from the satellite? If so, how reliable is it when it comes to giving a time for the users' current location? I ask because we are looking into ways of verifying the device has the correct time for the current user and if we can use this, we might not need to use a time server which relies on WiFi.

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

PiCroft posted:

I have a quick question on the Android Location framework - I notice it has a getTime() method.

When testing, I noticed that if I set the device clock forward 6 hours and waited for a location update, the system time reported my current time +6 hours (unsurprisingly) but the location time reported my current, correct time.

My question is, where does the getTime() come from? Does it come from the satellite? If so, how reliable is it when it comes to giving a time for the users' current location? I ask because we are looking into ways of verifying the device has the correct time for the current user and if we can use this, we might not need to use a time server which relies on WiFi.

It uses whatever generated the fix used for that Location object. This means that it's also using whatever vendor code was written to generate the fix, up to and including the OEM that "enhanced" the hardware on someone's phone.

I somewhat advise against relying on it (or anything else really), unless you can whitelist the devices you'll be using. It's PROBABLY fine, until you end up with the HTC Shitbird "helpfully" offsetting for DST or something.

hooah posted:

I did have them send a bug report from the settings menu, but my app shows up on logcat like three times, so that's not too helpful (assuming the person installed the verbose version). This'll be fun!

Use a logging framework that allows you to log to disk, have them send the log file.

PiCroft
Jun 11, 2010

I'm sorry, did I break all your shit? I didn't know it was yours

Volmarias posted:

It uses whatever generated the fix used for that Location object. This means that it's also using whatever vendor code was written to generate the fix, up to and including the OEM that "enhanced" the hardware on someone's phone.

I somewhat advise against relying on it (or anything else really), unless you can whitelist the devices you'll be using. It's PROBABLY fine, until you end up with the HTC Shitbird "helpfully" offsetting for DST or something.


Thanks, we can guarantee (at least for the moment) that the devices in question are the Galaxy S3 Mini and only that device. From what I read, the time depends on what provider has been set - adding a GPS provider provides a satellite time and a network provider returns a time from the network, which I haven't found much info on - wether it comes from an NTP server or comes from the network device its connected to or whatever.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Volmarias posted:

I somewhat advise against relying on it (or anything else really), unless you can whitelist the devices you'll be using. It's PROBABLY fine, until you end up with the HTC Shitbird "helpfully" offsetting for DST or something.

The API description seems pretty clear that it's UTC and has to be. If the fix were based on the system clock, then the location would be catastrophically wrong whenever the system clock drifted or was reset specifically; GPS depends on high-reliability timing to function.

It doesn't seem like this API would be any less reliable across implementations than any other arbitrary Android API. Is there a history of problems with it that I don't know about?

Glimm
Jul 27, 2005

Time is only gonna pass you by

React Native for Android is now available:

http://facebook.github.io/react-native/

Time to re-write all of our apps??

Tunga
May 7, 2004

Grimey Drawer

Subjunctive posted:

The API description seems pretty clear that it's UTC and has to be. If the fix were based on the system clock, then the location would be catastrophically wrong whenever the system clock drifted or was reset specifically; GPS depends on high-reliability timing to function.
Note, however, that it is the time of the most recent location update, which might not be right now.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Tunga posted:

Note, however, that it is the time of the most recent location update, which might not be right now.

Right, it's the time of the fix.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Glimm posted:

React Native for Android is now available:

http://facebook.github.io/react-native/

Time to re-write all of our apps??

I'm excited to get back into Android dev with this.

React for the web is fantastic.

Adbot
ADBOT LOVES YOU

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Subjunctive posted:

The API description seems pretty clear that it's UTC and has to be. If the fix were based on the system clock, then the location would be catastrophically wrong whenever the system clock drifted or was reset specifically; GPS depends on high-reliability timing to function.

It doesn't seem like this API would be any less reliable across implementations than any other arbitrary Android API. Is there a history of problems with it that I don't know about?

Manufacturers make mistakes that break CTS, then push out an update never several months after public discovery. There's nothing particular to this one, I just advise caution on assuming that a manufacturer hasn't invalidated a fundamental assumption in a place like this. Look out for some devices that always return zero here, I've seen that happen for sure, I haven't seen an otherwise inaccurate timestamp however.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply