Sunday, June 4, 2017

Configuring and accessing flatDir repositories in gradle

Lets assume there are two projects: Project1/module1 and Project2/module2, and module2 depends on a JAR file built by module1.

Step 1: Declare repository in Project2/module2/build.gradle

repositories {
    flatDir {
        dirs new File(project.rootDir, 
                      "/../Project1/module1/build/libs")
    }
}

Step 2: Declare dependency in Project2/module2/build.gradle

dependencies {
    compile ':module1-1.0-SNAPSHOT'
}

All you need to do now is to run JAR gradle task in Project1/module1.  It'll place module1-1.0.SNAPSHOT.jar into Project1/module1/build/libs folder.  After that Project2/module2 will be able to access that jar.  Note that you need a colon (':') in front of 'module1-1.0-SNAPSHOT'.

This quick solution works really well if you need to iterate fast and don't want to setup a local maven repository.

Wednesday, May 31, 2017

Delimiters in ST4's imports

A rule: 

Template files that are being imported should explicitly specify delimiters.  

If they don't, the delimiters of the file that has import statement will be used. If these delimiters are different from the delimiters of the imported file, the template will not be properly rendered.

Sunday, May 21, 2017

Testing Content Providers with Robolectric

There are many samples of testing content providers with Robolectric that seem incorrect.  They would instantiate content provider directly, manually call onCreate(), and then register the provider with the shadow content resolver.  But when you do this, the provider's getContext() will return null if you call it from within onCreate() method.

What seems to work is the following:

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class ProviderTestJUnit {
    private static final String AUTHORITY = “com.example.provider";
    private Context context;

    @Before
    public void setUp() {
        context = RuntimeEnvironment.application;
        ShadowContentResolver.registerProviderInternal(AUTHORITY,
                Robolectric.setupContentProvider(Provider.class));
    }

    @Test
    public void simpleQuery() {
        final ContentResolver cr = context.getContentResolver();
        final Uri uri = new Uri.Builder()
                .scheme(ContentResolver.SCHEME_CONTENT)
                .authority(AUTHORITY).build();
        final Cursor cursor = cr.query(uri, null, null, null, null);
        assertNotNull(cursor);
    }
}

When you call ShadowContentResolver.registerProviderInternal(), the content provider is created, properly initialized, and then its onCreate() is called.  Calling getContext() from within onCreate() will return non-null context.

After simple setUp() initialization the test will run.  The test code looks the same as if you tested your provider on an emulator or a device.


Saturday, May 20, 2017

Testing Content Providers (again)

This earlier post describes how to fix content provider tests.  Another way to fix them is to make setUp() method public and annotate it with @Before attribute:

@Before
@Override
public void setUp() throws Exception {
    setContext(InstrumentationRegistry.getTargetContext());
    super.setUp();
}

Note that the method should be implemented as described Testing Your Content Provider.

Listing folders first in OSX Finder

A short version of the original post:


Saturday, April 8, 2017

Loaders 1.2.0 is released

A new version of the loaders library, 1.2.0, which now also works with Loaders from Android support library, is released.
A sample application that demonstrates the usage of the library was also released today.

Saturday, March 18, 2017

SELECT LIKE FROM LIKE WHERE LIKE LIKE LIKE

SQLite documentation clearly says about not using keywords as the names of named objects.  For example, using a keyword as a table name

CREATE TABLE UNIQUE (
    a TEXT
);

leads to the following syntax error:

Error while executing SQL query on database 'provider': near "UNIQUE": syntax error

But this is not true for all keywords.  Let's try LIKE as a table name:

CREATE TABLE LIKE (
    a TEXT
);

No error, the table is created.  Let's try LIKE as a column name:

CREATE TABLE LIKE (
    LIKE TEXT
);

No problem.

INSERT INTO LIKE (LIKE) VALUES('LIKE');

Also works.  And now is the best example:

SELECT LIKE FROM LIKE WHERE LIKE LIKE LIKE;

Compiles, runs and returns correct results.  You don't even need to put quotes around the last LIKE.