Categories
discuss

Android NDK in Android studio >=1.4

I do not consider this question to be a duplicate of this and this questions since they are mainly answered by this link and that is not adaptable for later versions of AS.

I can find good information on how to integrate Android NDK with Eclipse, but that Eclipse and ADT is now considered deprecated by Google.

When following the instructions to setup a project for the experimental gradle plugin I get numerous errors in the editor of type cannot Resolve symbol for all the new additions as well as the error posted below after the build.

The build.gradle in project.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle-experimental:0.2.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

And the build.gradle in app

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

model{
    android {
         compileSdkVersion = 22
        buildToolsVersion = "23.0.1"

         defaultConfig.with {
             applicationId = "se.einarsundgren.gstreamandroiddemo"
             minSdkVersion.apiLevel = 22
            targetSdkVersion.apiLevel = 22
            versionCode = 1
            versionName = "1.0"

             buildConfigFields.with {
                 create() {
                     type = "int"
                     name = "VALUE"
                     value = "1"
                }
            }
        }

         android.buildTypes {
             release {
                 minifyEnabled = false
                 proguardFiles += file('proguard-rules.pro')
            }
        }

         android.productFlavors {
             create("flavor1") {
                 applicationId = 'com.app'
            }
        }

         android.sources{
             main {
                 java {

                   source {
                         srcDir 'src'
                      }
                  }
            }
        }

        android.ndk {
            moduleName = "native"
        }
 }
}

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

The error I get when cleaning and rebuilding the project:

Error:A problem occurred configuring root project ‘GstreamAndroidDemo’.

Could not resolve all dependencies for configuration ‘:classpath’. Could not resolve com.android.tools.build:gradle-experimental:0.2.0. Required by: :GstreamAndroidDemo:unspecified Could not resolve com.android.tools.build:gradle-experimental:0.2.0. Could not get resource ‘https://jcenter.bintray.com/com/android/tools/build/gradle-experimental/0.2.0/gradle-experimental-0.2.0.pom‘. Could not GET ‘https://jcenter.bintray.com/com/android/tools/build/gradle-experimental/0.2.0/gradle-experimental-0.2.0.pom‘. peer not authenticated

How do I integrate the NDK with a project in Android Studio? The previously linked questions have answers valid for an earlier version (pre 1.3) and the instructions are not adaptable for AS 1.4

Answer

that this setting where you can point to the location of the NDK is not included in the later versions.

Yes, it is, at least on Android Studio 1.4.1 on Linux:

Project Structure Dialog, SDK Location Category

How do I integrate the NDK with a project in Android Studio?

As far as I am aware, you follow the instructions.


UPDATE: With regard to your gradle-experimental problems, 0.2.0 and newer versions certainly show up in jcenter when you view their Web site. Make sure that you have followed the rest of the instructions, such as using Gradle 2.5.

Categories
discuss

findFragmentByTag null for Fragment A, if setRetain(true) on Fragment B

My problem involves an activity hosting three support fragments. One is a normal programmatic fragment (let’s call it a home fragment). One is a portrait fragment added on top of the home fragment when the device is orientated, and one is ‘headless’, to continue an async task regardless of configuration changes. Very simple, I was working off this nice example.

public class HeadlessCustomerDetailFetchFragment extends Fragment{
private RequestCustomerDetails mRequest;
private AsyncFetchCustomerDetails mAsyncFetchCustomerDetails;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

    mRequest = (RequestCustomerDetails)getActivity();
}

public void startFetching(String scannedBarcode) {
    if(mAsyncFetchCustomerDetails != null && mAsyncFetchCustomerDetails.getStatus() == AsyncTask.Status.RUNNING) return;

    if(mAsyncFetchCustomerDetails == null || mAsyncFetchCustomerDetails.getStatus() == AsyncTask.Status.FINISHED)
        mAsyncFetchCustomerDetails = new AsyncFetchCustomerDetails(getActivity(), mRequest, mPartner, scannedBarcode);
}

public void stopFetching() {
    if(mAsyncFetchCustomerDetails != null && mAsyncFetchCustomerDetails.getStatus() != AsyncTask.Status.RUNNING) return;
    mAsyncFetchCustomerDetails.cancel(true);
}

}

In my activity’s onCreate() I create and add the headless fragment if necessary.

 mHeadlessCustomerDetailFetchFragment = (HeadlessCustomerDetailFetchFragment)getSupportFragmentManager()
            .findFragmentByTag(HeadlessCustomerDetailFetchFragment.class.getSimpleName());

if(mHeadlessCustomerDetailFetchFragment == null) {
         mHeadlessCustomerDetailFetchFragment = HeadlessCustomerDetailFetchFragment.instantiate(this, HeadlessCustomerDetailFetchFragment.class.getName());
    getSupportFragmentManager().beginTransaction()
            .add(mHeadlessCustomerDetailFetchFragment, mHeadlessCustomerDetailFetchFragment.getClass().getSimpleName())
            .commit();
    getSupportFragmentManager().executePendingTransactions();
        id = null;
    }

I then launch an async task (via my startFetching() function) after a 6 second delay (for testing) kicked off in the onCreateView() of the portrait fragment that is added when the orientation changes to portrait. The orientation change is detected in the activity’s onCreate():

if (savedInstanceState == null) { 
   // Do some initial stuff for the home fragment
} 
else {
    getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Launch portrait fragment
        FragmentLauncher.launchPortraitFragment(this);
    }

When the task is finished, I return to the activity and attempt to update the UI of the active portrait fragment, but the fragment manager cannot find it, findFragmentByTag() returns null.

To be clear:

  • The tag is correct
  • The fragment is found if I do not orientate the device, and instead kick off the async task somewhere else, during the activity’s onResume() for example.
  • If I do not tell the headless fragment to retain itself – thereby losing the benefit of not recreating it, the portrait fragment is also correctly found.
  • Debugging I can see all 3 fragments in the manager if the headless one is not set to retain itself. If it is, I can only see the headless fragment.

Maybe retaining a fragment aggressively kills other fragments that are not retained or something to that effect?

Answer

The root of the problem is how you maintain the reference to activity inside headless fragment.
It is not clear from the provided code how you update UI after completion of AsyncTask, lets assume you use mRequest from the first code snippet. You give mRequest to constructor when you need new AsyncTask and use this reference after AsyncTask completes.
It is ok, when you have no screen rotation between the moment when activity is created and when UI is updated. It is because you use the reference to activity which is still active.
It is not ok if you rotate screen. You have new activity every time after rotation. But mRequest is assigned only once when you create headless fragment in first call of activity’s onCreate(). So it contains reference to the first instance of activity which is not active after rotation. There are 2 instances of activity after rotation in your case: the first – which is referenced by mRequest and the second – which is visible and active. You can confirm this by logging the reference of activity inside onCreate: Log.i(TAG, "onCreate: this=" + this); and inside activity’s method which updates UI after async task: Log.i(TAG, "updating UI: this=" + this);
Besides the first activity is in Destroyed state. All fragments are detached from this activity and non retained fragments are destroyed. That’s why findFragmentByTag returns null.
If the headless fragment is not set to retain itself, then activity’s onCreate() recreates it in every call. So mRequest always references the last created activity with all fragments. In this case findFragmentByTag returns not null.

To avoid this problem I suggest:

  1. Use weak reference to store reference of Activity. Something like this:
    private WeakReference<RequestCustomerDetails> mRequest;
  2. Create a method in HeadlessCustomerDetailFetchFragment to update this reference.
    public void updateResultProcessor(RequestCustomerDetails requestCustomerDetails) { mRequest = new WeakReference(requestCustomerDetails); // Update ui if there is stored result of AsyncTask (see p.4b) }
  3. Call this method from activity’s onCreate() every time.
  4. When AsyncTask finishes:
    a) if mRequest.get() is not null then update UI.
    b) if mRequest.get() is null then store result inside headless fragment and use it in p.2.

    Weak reference will allow GC to process destroyed activity and set null inside weak reference. Null inside weak reference will signal that there is no UI and nothing to update. Storing result of AsyncTask in headless fragment will allow to use this result for updating UI after its recreation.

    Hope this will help. Sorry for my English. If something is unclear I will try to explain.
Categories
discuss

How to include JAR dependency into an AAR library

Summary:

I have an AAR file that depends on a JAR file, when I build the AAR project, it doesn’t contain the JAR code.

Details:

I have a Java SDK library project that contains code that we use for Java web projects and such, this library is created using Gradle and resides in an internal nexus server (as a JAR).

The goal is to provide an “Android configured” version of this JAR library through an AAR library that multiple Android Applications can use and minimize the effort (and boilerplate code) to implement it. This AAR file is also uploaded to the nexus server to be used by the Android Application projects.

My AAR project includes a gradle dependency for my Java SDK library (the JAR) but when built, the AAR doesn’t include any classes from it.

Code:

This is the Java SDK project’s gradle file:

apply plugin: 'java'

//noinspection GroovyUnusedAssignment
sourceCompatibility = 1.7
version = '1.1.1'

repositories {
    mavenCentral()
}

jar {
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    testCompile 'org.apache.directory.studio:org.apache.commons.io:2.4'
    compile 'org.springframework:spring-web:3.1.1.RELEASE'
    compile 'com.google.code.gson:gson:2.3'
}

This is the gradle file for my AAR Project, note that I removed the Maven repository declarations to my nexus server from it. I guess it shouldn’t matter for the sake of this question.

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "2.2.2"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
    }
}

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

    compile ('com.mycompany:javasdk:1.1.1')
}

This is the gradle file for my Android Project, again I removed the nexus server references:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.mycompany.application1"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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

    compile ('com.mycompany:androidsdk:2.2.2@aar')
}

NOTE: I initially solved the issue by adding the JAR in the lib directory of the AAR project, but this is undesired. It makes having a nexus server useless. It would be good that we can just bump the JAR’s version number in the AAR project’s gradle file and the update happens automatically at compile time.

NOTE2: I tried adding transitive=true to my AAR dependency in the Android Project but it didn’t solved anything, the real issue is that when building the AAR project, the JAR project code doesn’t get bundled.

Answer

You can add this task:

task copyLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

Dependencies will be downloaded from your Nexus, but when you need package the library, execute this task first and jar files will be copied and included inside final aar.

Categories
discuss

Object has-property-deep check in JavaScript

Let’s say we have this JavaScript object:

var object = {
   innerObject:{
       deepObject:{
           value:'Here am I'
       }
   }
};

How can we check if value property exists?

I can see only two ways:

First one:

if(object && object.innerObject && object.innerObject.deepObject && object.innerObject.deepObject.value) {
    console.log('We found it!');
}

Second one:

if(object.hasOwnProperty('innerObject') && object.innerObject.hasOwnProperty('deepObject') && object.innerObject.deepObject.hasOwnProperty('value')) {
    console.log('We found it too!');
}

But is there a way to do a deep check? Let’s say, something like:

object['innerObject.deepObject.value']

or

object.hasOwnProperty('innerObject.deepObject.value')

Answer

There isn’t a built-in way for this kind of check, but you can implement it easily. Create a function, pass a string representing the property path, split the path by ., and iterate over this path:

Object.prototype.hasOwnNestedProperty = function(propertyPath) {
  if (!propertyPath)
    return false;

  var properties = propertyPath.split('.');
  var obj = this;

  for (var i = 0; i < properties.length; i++) {
    var prop = properties[i];

    if (!obj || !obj.hasOwnProperty(prop)) {
      return false;
    } else {
      obj = obj[prop];
    }
  }

  return true;
};

// Usage:
var obj = {
  innerObject: {
    deepObject: {
      value: 'Here am I'
    }
  }
}

console.log(obj.hasOwnNestedProperty('innerObject.deepObject.value'));
Categories
discuss

Remove image from cache in Glide library

I am using Glide in one of my projects to show image from file.

Below is my code how I am showing the image:

Glide.with(DemoActivity.this)
     .load(Uri.parse("file://" + imagePath))
     .into(mImage);

The image at this location(imagePath) keeps on changing. By default Glide cache the image it shows in the ImageView. Because of this, the Glide was showing the first image from cache for new images at that location.

If I change the image at location imagePath with some other image having same name then the Glide is showing the first image instead of new one.

Two queries are:

  1. Is it possible to always the image from File and not cache? This way problem will be solved.

  2. Is it possible to clear image from cache before getting newly replaced image? This will also solve the problem.

Answer

This is how I solved this problem.

Method 1: When the URL changes whenever image changes

Glide.with(DemoActivity.this)
    .load(Uri.parse("file://" + imagePath))
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .skipMemoryCache(true)
    .into(mImage);

diskCacheStrategy() can be used to handle the disk cache and you can skip the memory cache using skipMemoryCache() method.

Method 2: When URL doesn’t change, however, image changes

If your URL remains constant then you need to use Signature for image cache.

Glide.with(yourFragment)
     .load(yourFileDataModel)
     .signature(new StringSignature(yourVersionMetadata))
     .into(yourImageView);

Glide signature() offers you the capability to mix additional data with the cache key.

  • You can use MediaStoreSignature if you are fetching content from media store. MediaStoreSignature allows you to mix the date modified time, mime type, and orientation of a media store item into the cache key. These three attributes reliably catch edits and updates allowing you to cache media store thumbs.
  • You may StringSignature as well for content saved as Files to mix the file date modified time.
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..