#StackBounty: #android #android-edittext stop input in edit text field but still keep the field focused

Bounty: 50

I have a EditText field, variable name valueInputField.

I listen to the text input change, what I want to achieve is during inputting, when the input format DOESN’T matches a regular expression, I would like to stop showing more inputs, but keep the field focused & user is able to type on keyboard still just that no real effect will take to the field.

@OnTextChanged(R.id.value_input)
protected void onTextChanged(CharSequence charSequence) {
   String inputChars = charSequence.toString().trim();
   // if doesn't match regular expression, stop showing more inputs
   if (!inputChars.matches(MY_REGEXP)) {
      // this doesn't achieve what I need.
      valueInputField.setInputType(0)
   }
}

I tried above way, it doesn’t work. How to achieve what I need?


Get this bounty!!!

#StackBounty: #android #intellij-idea #android-source #android-studio-3.0 Developing AOSP with Android Studio 3.1 Cannot build test apk…

Bounty: 200

I am trying to build a customized AOSP (on Android M, api 23) using Android Studio because I want to run instrumented tests on custom apps running on the hardware. This is on ubuntu 64. It is very frustrating for me as there is no clear cut path.

I ran the script

~/myAOSP/development/tools/idegen/intellij-gen.sh myApp company/apps/MY_APP

and opened MY_APP.iml in Android Studio.

Now I am trying to build the apk using gradle just for my project, and also the test apk.

The main myAOSP uses makefiles.

I am trying to build, but it cannot find junit-4.12

I put the jars into the local libs folder via a soft link

ln -s  ../../../prebuilts/devtools/tools/lib libs

which definitely has junit-4.12.jar

Failed to resolve: junit:junit:4.12

I followed the instructions here and also used the build.gradle as a template https://developer.android.com/studio/intro/migrate#migrate-intellij

// This buildscript{} block configures the code driving the build
buildscript {
   /**
    * The nested repositories{} block declares that this build uses the
    * jcenter repository.
    */
    repositories {
        jcenter()
        google()
    }

   /**
    * This block declares a dependency on the 3.1.0 version
    * of the Gradle plugin for the buildscript.
    */
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
    }
}

/**
 * This line applies the com.android.application plugin. Note that you should
 * only apply the com.android.application plugin. Applying the Java plugin as
 * well will result in a build error.
 */
apply plugin: 'com.android.application'

/**
 * This dependencies block includes any dependencies for the project itself. The
 * following line includes all the JAR files in the libs directory.
 */
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    testImplementation 'junit:junit:4.12'
    // Add other library dependencies here (see the next step)
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
}

/**
 * The android{} block configures all of the parameters for the Android build.
 * You must provide a value for at least the compilation target.
 */
android {
    compileSdkVersion 23
    buildToolsVersion '27.0.3'
    defaultConfig {
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    /**
    * This nested sourceSets block points the source code directories to the
    * existing folders in the project, instead of using the default new
    * organization.
    */
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        // Move the tests to tests/java, tests/res, etc...
        androidTest.setRoot('tests')

       /**
        * Move the build types to build-types/<type>
        * For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        * This moves them out of them default location under src/<type>/... which would
        * conflict with src/ being used by the main source set.
        * Adding new build types or product flavors should be accompanied
        * by a similar customization.
        */
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
     }
}

repositories {
    google()
}

I saw posts like Developing AOSP with Android Studio but they are out of date or not relevant.
Also http://ronubo.blogspot.com/2016/01/debugging-aosp-platform-code-with.html?view=magazine and Error:(23, 17) Failed to resolve: junit:junit:4.12

I am looking for a working solution to the problem of building an instrumented test apk for an app in customized AOSP, and running instrumented tests on it, in Android Studio 3.1 (or later).

a) if it is possible to build the instrumented test apk in gradle AS 3.1 (or later), then please suggest a fix to the gradle error shown.

b) if gradle build in a) above is NOT possible, then do I need to build instrumented test apk using the current makefiles in the customized AOSP?

c) if I build the instrumented test apk using makefiles, then can I still use the instrumentation UI in AS to run the tests on the hardware?


Get this bounty!!!

#StackBounty: #libgdx #android #shaders #glsl #fragment-shader Weird shader behavior on different devices

Bounty: 50

I’m trying to combine an ordinary shader with a Single Distance Field shader (for fonts and scalable icons) into one shader program.
The idea is simple – if uv.x is less than 1.0, it is drawn as usual, and if more than 1.0 then SDF is used (using GL_REPEAT uv.x and uv.x + 1.0 look similar)

Fragment shader code:

precision mediump float;
precision mediump int;

uniform sampler2D u_texture;
varying vec4 v_color;
varying vec2 v_texCoords;
uniform float u_smoothing;

void main() {
  // SDF
  float distance = texture2D(u_texture, v_texCoords).a;
  float alpha = smoothstep(0.5 - u_smoothing, 0.5 + u_smoothing, distance);
  vec4 sdfColor = vec4(v_color.rgb, alpha * v_color.a);

  // Regular
  vec4 regularColor = v_color * texture2D(u_texture, v_texCoords);

  // Making a choice
  gl_FragColor = mix(regularColor, sdfColor, step(1.0, v_texCoords.x));
}

It works and looks fine on desktop and most of popular Android devices but not on Oneplus One, Xiaomi Redmi 4A and Moto G devices.
This is how it must look like and how it actually looks on desktops and many other devices (Samsung S8, Xiaomi 3s, Pixel 2 etc.):
Normaly rendered

And this is how it looks like on Moto G, Oneplus One & some others:
enter image description here

I tried to find a problematic function, but without success.
First I tried to use the usual condition instead of mix():

void main() {
  // ...

  // Making a choice
  // gl_FragColor = mix(regularColor, sdfColor, step(1.0, v_texCoords.x));
  if (v_texCoords.x < 1.0) {
    gl_FragColor = regularColor;
  } else {
    gl_FragColor = sdfColor;
  }
}

Nothing has changed – this shader works well on most devices and is still bad on some others.
I decided that the problem lies in the calculation of sdfColor and changed fragment shader code a bit to check:

void main() {
  // ...

  // Making a choice
  gl_FragColor = sdfColor;  // Always using SDF
}

But this shader worked equally on all devices, which indicates that sdfColor is calculated correctly. This next screenshot was taken on Moto G:
enter image description here

Then I tried to differentiate the regions of textures with different colors:

void main() {
  // ...

  // Making a choice
  if (v_texCoords.x < 1.0) {
    gl_FragColor = regularColor;
    gl_FragColor.r = 1.0;  // Full red channel for regular texture regions without SDF (UV.x < 1.0)
  } else {
    gl_FragColor = sdfColor;
    gl_FragColor.r = 0.0;  // No red channel for SDF 
  }
}

On Moto G and other devices it looks as expected:
enter image description here

It seems to me that using mix() or conditions implicitly changes something else.


Get this bounty!!!

#StackBounty: #android #android-download-manager #android-fileprovider FileProvider not working with Failed to find configured root tha…

Bounty: 50

I am trying to imlement downloading and sharing PDF file for read by another PDF reader apps (DropBox, Drive PDF Reader or Adobe Reader) on Android using FileProvider way.

However, I keep getting the following exception:

Failed to find configured root that contains /storage/emulated/0/Android/data/com.my.app/files/docs/my_file_name.pdf

I first send the URL to Android DownloadManager to perform the downloading and then receive the result using BroadcastReceiver

My implementation as follow:

file_paths.xml

<paths>

    <external-files-path
        name="my_docs"
        path="docs" />

</paths>

AndroidManifest.xml

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">

    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />

</provider>

And from MainActivity:

public void downloadFile(String urlString) {
    Uri uri = Uri.parse(urlString);

    String filename = "my_file_name.pdf";

    DownloadManager.Request request = new DownloadManager.Request(uri);
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);

    request.setTitle("App is Downloading a File");
    request.setDescription("Downloading PDF File For App");

    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    request.setDestinationInExternalFilesDir(mContext, "docs", filename);

    request.allowScanningByMediaScanner();

    mDownloadManager.enqueue(request);
}

And finally from my custom BroadcastReceiver:

uriString is taken from a cursor.getString(uriIndex) using downloadManager.query(myQuery) the usual way.

private void startDocumentReaderUsingFileProvider(Context context, String uriString) {
    Uri parsedUri = Uri.parse(uriString);

    File file = new File(parsedUri.getPath());
    String packageName = context.getApplicationContext().getPackageName();

    // Exception thrown from the following line.
    Uri uri = FileProvider.getUriForFile(context, packageName + ".fileprovider", file);

    startActivity(context, uri);
}

private void startActivity(Context context, Uri uri) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(uri, "application/pdf");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    Intent chooser = Intent.createChooser(intent, "Display PDF Reader");

    context.startActivity(chooser);
}

Exception stack trace:

FATAL EXCEPTION: main
    Process: com.my.app, PID: 8972
    java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=com.my.app bqHint=4 (has extras) } in com.my.app.FileBroadcastReceiver@82a2a7
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1003)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:158)
        at android.app.ActivityThread.main(ActivityThread.java:7229)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
     Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.my.app/files/docs/my_file_name.pdf
        at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:678)
        at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:377)
        at com.my.app.FileBroadcastReceiver.startDocumentReaderUsingFileProvider(FileBroadcastReceiver.java:85)
        at com.my.app.FileBroadcastReceiver.startDocumentReader(FileBroadcastReceiver.java:69)
        at com.my.app.FileBroadcastReceiver.onReceive(FileBroadcastReceiver.java:43)
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:993)
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:158) 
        at android.app.ActivityThread.main(ActivityThread.java:7229) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
06-07 12:56:50.981 8972-9463/com.my.app E/com.worklight.common.Logger$UncaughtExceptionHandler: Logger$UncaughtExceptionHandler.uncaughtException in Logger.java:442 :: Uncaught Exception
    java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=com.my.app bqHint=4 (has extras) } in com.my.app.FileBroadcastReceiver@82a2a7
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1003)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:158)
        at android.app.ActivityThread.main(ActivityThread.java:7229)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
     Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.my.app/files/docs/my_file_name.pdf
        at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:678)
        at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:377)
        at com.my.app.FileBroadcastReceiver.startDocumentReaderUsingFileProvider(FileBroadcastReceiver.java:85)
        at com.my.app.FileBroadcastReceiver.startDocumentReader(FileBroadcastReceiver.java:69)
        at com.my.app.FileBroadcastReceiver.onReceive(FileBroadcastReceiver.java:43)
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:993)
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:158) 
        at android.app.ActivityThread.main(ActivityThread.java:7229) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 


Get this bounty!!!

#StackBounty: #android #soap #tls1.2 #android-ksoap2 Using a TLS1.2 client certificate in kSoap2

Bounty: 100

I’m trying to connect my Android app to a TLS-secured SOAP endpoint using kSoap2 and EasyWSDL, but I’m getting the following exception:

W/System.err: javax.net.ssl.SSLHandshakeException: Connection closed by peer
                  at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
                  at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:351)
                  at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:192)
                  at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:149)
W/System.err:     at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:112)
                  at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:184)
                  at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
                  at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
                  at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
                  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
                  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
                  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:258)
                  at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
                  at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(Unknown Source:0)
                  at org.ksoap2.transport.HttpsServiceConnectionSE.openOutputStream(HttpsServiceConnectionSE.java:127)
                  at com.easywsdl.exksoap2.mtom.MTOMTransportImplementation.sendData(MTOMTransportImplementation.java:65)
                  at com.easywsdl.exksoap2.transport.AdvancedHttpsTransportSE.sendData(AdvancedHttpsTransportSE.java:39)
                  at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:184)
                  at com.easywsdl.exksoap2.transport.AdvancedHttpsTransportSE.call(AdvancedHttpsTransportSE.java:51)

Here is how I’m configuring my Transport:

@Override
    protected Transport createTransport() {
        Transport transport = super.createTransport();
        try {
            if(transport instanceof HttpsTransportSE) {
                HttpsTransportSE httpsTransport = (HttpsTransportSE)transport;
                if(httpsTransport.getServiceConnection() instanceof HttpsServiceConnectionSE) {
                    HttpsServiceConnectionSE httpsServiceConnection = (HttpsServiceConnectionSE)httpsTransport.getServiceConnection();
                    httpsServiceConnection.setSSLSocketFactory(getSSLSocketFactory());
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Could not add key store", e);
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "Could not add key store", e);
        } catch (KeyStoreException e) {
            Log.e(TAG, "Could not add key store", e);
        } catch (KeyManagementException e) {
            Log.e(TAG, "Could not add key store", e);
        }
        this.transport = transport;
        return transport;
    }

    private SSLSocketFactory getSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);
        return context.getSocketFactory();
    }

I’m not sure how to troubleshoot this or if I’m using the keystore right. Please help.


Get this bounty!!!

#StackBounty: #android #android-ndk #android-support-library #renderscript #android-rendering Renderscript not generating librs.xx.so i…

Bounty: 50

I’m using renderscript for audio dsp processing. It works well until I decided to bump up renderscriptTargetApi version from 19 to 24 in an attempt to make use of newer renderscript APIs in a backward compatible way.

There is no issue with the compilation, but at runtime, logcat shows error like this

05-31 19:40:23.097 8661-8734/com.example.audio.test E/RenderScript:
Unable to open shared library
(/data/user/0/com.example.audio.test//lib/librs.xx.so): dlopen failed:
library “libRSSupportIO.so” not found

If I have renderscriptTargetApi as 19 or 20, my apk has librs.xx.so and there is no error. If I bump it to 21, 23, or 24, librs.xx.so is not generated and thus I have this runtime error.

I’m using renderscript through NDK i.e. C++. Also using CMake. There aren’t instructions I could find to make use of renderscript support library through NDK. All instructions assume that the support library is used through Java.

This is from build.gradle

    ndk {
        abiFilters 'armeabi-v7a', 'x86'
    }

    renderscriptTargetApi 24
    renderscriptSupportModeEnabled true
    renderscriptNdkModeEnabled true

CMakeLists.txt has

add_library (dsp SHARED
  ${SRC_PATH}/dsp.cpp
  ${SRC_RS_PATH}/xx.rs ${SRC_RS_GENERATED_PATH}/ScriptC_xx.cpp)

target_compile_options(dsp PRIVATE 
  -std=c++11 -stdlib=libc++ -fno-rtti -fexceptions -Ofast)

target_link_libraries(dsp RScpp_static dl ${log-lib})

This is xx.rs

#pragma version(1)
#pragma rs java_package_name(com.example.audio)
#pragma rs_fp_relaxed

float RS_KERNEL my_kernel(float in, uint32_t x) {
    // ...
}

This is how the kernel is called from C++

sp<RS> rs = new RS();
rs->init(app_cache_dir);

sp<const Element> e = Element::F32(rs);
sp<const Type> t = Type::create(rs, e, 44100*10, 0, 0);

sp<Allocation> inAlloc = Allocation::createTyped(rs, t);
inAlloc->copy1DFrom(input);

sp<Allocation> outAlloc = Allocation::createTyped(rs, t);

ScriptC_xx *script = new ScriptC_xx(rs);
script->forEach_xx(inAlloc, outAlloc);

outAlloc->copy1DTo(output);

As you see, it is pretty basic usage scenario of renderscript. It works well with renderscriptTargetApi in 19 or 20. If I bump up the version, build is still successful, but librs.xx.so file is not generated. At runtime, we see the above mentioned error about this .so file.

What am I missing here? I tried manipulating my minSdkVersion which I think is unrelated to renderscript target api. It didn’t help.

How can I use the newer renderscript APIs in the backward compatible manner from NDK? Any help is appreciated.

Repo to reproduce the issue

https://github.com/rpattabi/renderscript-ndk-cmake

I’ve filed a bug report on Android build system about this: https://issuetracker.google.com/issues/109578956


Get this bounty!!!

#StackBounty: #wifi #android #android-things Android things create Wi-Fi access point to configure device

Bounty: 100

I need to send Wi-Fi credentials to my Android Things headless device via a mobile app. As it is right now, the device advertises on Bluetooth, the mobile app connects to device and sends Wi-Fi credentials to it. The device then stops advertising via Bluetooth and connects directly to the users Wi-Fi network using the credentials acquired via Bluetooth.

Is it possible to set up the device to advertise via Wi-Fi instead of Bluetooth? If so how could this be done? I can’t find any information or tutorials on the subject probably because android things is still relatively new.

Looking for any advice/libraries/tutorials to send me in the right direction.


Get this bounty!!!

#StackBounty: #android Too much margin on SearchView

Bounty: 50

My SearchView is showing up like this:

enter image description here

As you can see there is a margin both on the search_edit_frame of the SearchView, and outside the SearchView itself.

enter image description here

Where is this coming from? Inspecting the layout reveals a margin of 24 pixels to the left of search_edit_frame but no margin elsewhere.

How can I remove this extra space?

menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/appbar_menu_search"
        android:icon="@drawable/ic_search"
        android:title="@string/search_search"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

Layout:

<RelativeLayout

    android:id="@+id/root_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.design.widget.AppBarLayout
        android:id="@+id/profile_appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/topbar_gradient"
        android:theme="@style/AppTheme.Dark"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/topbar_gradient"
            android:fitsSystemWindows="true"
            android:minHeight="?android:attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways">

        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>

    (...)
</RelativeLayout>

I managed to reduce the spacing by applying @Jimmy’s answer:

enter image description here

However theres still a big gap between the “back” imagebutton and the SearchView.


Get this bounty!!!

#StackBounty: #android #android-mediaplayer #live-wallpaper How to fit video in Live wallpaper, by center-crop and by fitting to width/…

Bounty: 400

Background

I’m making a live wallpaper that can show a video. In the beginning I thought this is going to be very hard, so some people suggested using OpenGL solutions or other, very complex solutions (such as this one).

Anyway, for this, I’ve found various places talking about it, and based on this github library (which has some bugs), I finally got it to work.

The problem

While I’ve succeeded showing a video, I can’t find the way to control how it’s shown compared to the screen resolution.

Currently it always gets to be stretched to the screen size, meaning that this (video taken from here) :

enter image description here

gets to show as this:

enter image description here

Reason is the different aspect ratio : 560×320 (video resolution) vs 1080×1920 (device resolution).

What I’ve tried

I tried to play with various fields and functions of the SurfaceHolder, but with no luck so far.

Here’s the current code I’ve made (full project available here) :

class MovieLiveWallpaperService : WallpaperService() {
    override fun onCreateEngine(): WallpaperService.Engine {
        return VideoLiveWallpaperEngine()
    }

    private enum class PlayerState {
        NONE, PREPARING, READY, PLAYING
    }

    inner class VideoLiveWallpaperEngine : WallpaperService.Engine() {
        private var mp: MediaPlayer? = null
        private var playerState: PlayerState = PlayerState.NONE

        override fun onSurfaceCreated(holder: SurfaceHolder) {
            super.onSurfaceCreated(holder)
            Log.d("AppLog", "onSurfaceCreated")
            mp = MediaPlayer()
            val mySurfaceHolder = MySurfaceHolder(holder)
            mp!!.setDisplay(mySurfaceHolder)
            mp!!.isLooping = true
            mp!!.setVolume(0.0f, 0.0f)
            mp!!.setOnPreparedListener { mp ->
                playerState = PlayerState.READY
                setPlay(true)
            }
            try {
                //mp!!.setDataSource(this@MovieLiveWallpaperService, Uri.parse("http://techslides.com/demos/sample-videos/small.mp4"))
                mp!!.setDataSource(this@MovieLiveWallpaperService, Uri.parse("android.resource://" + packageName + "/" + R.raw.small))
            } catch (e: Exception) {
            }
        }

        override fun onDestroy() {
            super.onDestroy()
            Log.d("AppLog", "onDestroy")
            if (mp == null)
                return
            mp!!.stop()
            mp!!.release()
            playerState = PlayerState.NONE
        }

        private fun setPlay(play: Boolean) {
            if (mp == null)
                return
            if (play == mp!!.isPlaying)
                return
            when {
                !play -> {
                    mp!!.pause()
                    playerState = PlayerState.READY
                }
                mp!!.isPlaying -> return
                playerState == PlayerState.READY -> {
                    Log.d("AppLog", "ready, so starting to play")
                    mp!!.start()
                    playerState = PlayerState.PLAYING
                }
                playerState == PlayerState.NONE -> {
                    Log.d("AppLog", "not ready, so preparing")
                    mp!!.prepareAsync()
                    playerState = PlayerState.PREPARING
                }
            }
        }

        override fun onVisibilityChanged(visible: Boolean) {
            super.onVisibilityChanged(visible)
            Log.d("AppLog", "onVisibilityChanged:" + visible + " " + playerState)
            if (mp == null)
                return
            setPlay(visible)
        }

    }

    class MySurfaceHolder(private val surfaceHolder: SurfaceHolder) : SurfaceHolder {
        override fun addCallback(callback: SurfaceHolder.Callback) = surfaceHolder.addCallback(callback)

        override fun getSurface() = surfaceHolder.surface!!

        override fun getSurfaceFrame() = surfaceHolder.surfaceFrame

        override fun isCreating(): Boolean = surfaceHolder.isCreating

        override fun lockCanvas(): Canvas = surfaceHolder.lockCanvas()

        override fun lockCanvas(dirty: Rect): Canvas = surfaceHolder.lockCanvas(dirty)

        override fun removeCallback(callback: SurfaceHolder.Callback) = surfaceHolder.removeCallback(callback)

        override fun setFixedSize(width: Int, height: Int) = surfaceHolder.setFixedSize(width, height)

        override fun setFormat(format: Int) = surfaceHolder.setFormat(format)

        override fun setKeepScreenOn(screenOn: Boolean) {}

        override fun setSizeFromLayout() = surfaceHolder.setSizeFromLayout()

        override fun setType(type: Int) = surfaceHolder.setType(type)

        override fun unlockCanvasAndPost(canvas: Canvas) = surfaceHolder.unlockCanvasAndPost(canvas)
    }
}

The questions

  1. How can I make the content fit the screen, without losing aspect ratio and without cropping (meaning there will be margins) ?
  2. How can I make it fill entire screen, without losing aspect ratio, and allowing content to crop (meaning like center-crop) ?


Get this bounty!!!

#StackBounty: #android #android-studio #android-productflavors Product flavors in Android Studio

Bounty: 100

I can not get product flavours working. I have this gradle

apply plugin: 'com.android.application'
android {
    defaultConfig {
      minSdkVersion 14
      targetSdkVersion 24
      compileSdkVersion 27
    }
    signingConfigs {
        release {
      }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
            signingConfig signingConfigs.release
        }
    }
    repositories {
        maven { url "https://jitpack.io" }
    }
    flavorDimensions "dim1", "dim2", "dim3"
    productFlavors {
        flavor1 {
            dimension "dim1"
            applicationId "com.example.dim1.app"
        }
        flavor3 {
            dimension "dim2"
            applicationId "com.example.dim2.app"
        }
        flavor3 {
            dimension "dim3"
            applicationId "com.example.dim3.app"
        }
    }
    sourceSets {
        flavor1 {
          java.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/java/"]
          manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example1/AndroidManifest.xml"
          assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/example1/assets/"]
          resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/example1/res/"]
        }
        flavor2 {
          manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example2/AndroidManifest.xml"
          manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example2/AndroidManifest.xml"
          assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/example2/assets/"]
          resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/example2/res/"]
        }
        flavor3 {
          manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example3/AndroidManifest.xml"
          manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example3/AndroidManifest.xml"
          assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/example3/assets/"]
          resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/example3/res/"]
        }
    }
}
dependencies {
    api 'com.google.android.gms:play-services-maps:15.0.0'
    api 'com.google.android.gms:play-services-location:15.0.0'
    api 'com.android.support:appcompat-v7:27.1.1'
    api 'com.github.PhilJay:MPAndroidChart:v2.0.8'

}

When I got to “Build | Select variant” I can only select

Module:app
Build Variant:flavor1Flavor2Flavor3Debug,flavor1Flavor2Flavor3Release

I would have liked to get

  • the following build variants: flavor1Debug,flavor2Debug,flavor3Debug,flavor1Release,flavor2Release,flavor3Release

I have tried “File | Sync project with gradle file”

I get this error

Caused by: java.lang.RuntimeException: Cannot read packageName from
W:android-studio-projectssharedidappsrcmainAndroidManifest.xml

I have tried to both

  • have no such file (hoping it would take the product flavor one?)
  • have the “main” manifest only define shared stuff between all product flavors


Get this bounty!!!