Monday, April 24, 2017

Maven: the most weird error causing failure to add JAR to local repository


To add a 3rd party JAR into Maven local repository on your local machine, you can run:

$ mvn install:install-file -Dfile=yourJarFile.jar -DgroupId=yourGroupID -DartifactId=yourArtifactId -Dversion=1.0 -Dpackaging=jar

The template of this command is available all over the internet. It is convenient to copy and paste the template and make your own changes to add the JARs you want. However, if you run the command and see this error:

[ERROR] The goal you specified requires a project to execute but there is no POM in this directory (......). Please verify you invoked Maven from the correct directory. -> [Help 1]

you don't need to scratch your head for the whole afternoon just like me.

Googling on the internet tells different reasons that may cause this problem. Some are weird, such as that in Powershell you have to add quotes for the parameters, i.e.

mvn install:install-file "-Dfile=yourJarFile.jar" "-DgroupId=yourGroupID" "-DartifactId=yourArtifactId" "-Dversion=1.0" "-Dpackaging=jar"

The reason causing my failure was even more weird. After a long time of research and experiment, I finally found out that the dash in my "-Dfile" was not an ASCII dash, but a UTF-8 en dash (0xE2 0x80 0x93). As my terminal was using UTF-8 charset, nobody could tell the difference -- but Maven.

So the lesson is, first, I should always set the terminal to use the ASCII charset. Secondly, try not to blindly copy and paste from the internet, where articles can be pasted in UTF-8.

And when Maven complains "The goal you specified requires a project to execute but there is no POM in this directory", we must understand it does not know what it is talking about. The reason could be that the input parameters are invalid. Don't hurry to add a pom.xml, just verify that your parameters are all good, char by char, and make sure they are all just simple ASCII.

Tuesday, March 7, 2017

Maven, Eclipse and Tomcat


When building a Maven project in Eclipse, this error may occur if the build goal is not set:
      No goals have been specified for this build.

To build it and start it with Tomcat:
  1. Right click on the project;
  2. Select Run As -> Maven build
  3. In the dialog, on the right side, find the Goals input. Input the goal: -Dmaven.tomcat.port=8080 tomcat:run
  4. Click the Run button. 

Monday, February 6, 2017

Android programming: Banner Ads


I managed to set up the banner ad in my little app. Here is the summary of the changes:
  • Set minSdkVersion to 9 or higher.
  • To use Firebase, add these dependencies and plugin to the app/build.gradle file:
dependencies {
...
    compile 'com.google.android.gms:play-services:10.0.1'
    compile 'com.google.firebase:firebase-ads:10.0.1'
    compile 'com.google.android.gms:play-services-ads:10.0.1'
}

apply plugin: 'com.google.gms.google-services'

  • Add this dependency to the project's build.gradle file:
dependencies {
        classpath 'com.google.gms:google-services:3.0.0'
        classpath 'com.android.tools.build:gradle:2.2.3'
}
  • Add permission to use INTERNET in app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
  • Add the Ad unit ID and app ID to the strings.xml file. The following shows the test IDs used in Google's example. To get the IDs for my real app, I went to the Admob web site and registered my app. Admob then generated the Ad unit ID and the app ID, and offered to send the IDs and setup instruction to my Email.
<string name="banner_ad_unit_id">ca-app-pub-3940256099942544/6300978111</string>
<string name="banner_ad_app_id">ca-app-pub-3940256099942544~3347511713</string>

  •  Now the real stuff, add the AdView widget to the app:
...
          xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"

          xmlns:ads="http://schemas.android.com/apk/res-auto"
...
<com.google.android.gms.ads.AdView
           android:id="@+id/adView"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_centerHorizontal="true"
           android:layout_alignParentBottom="true"
           ads:adSize="BANNER"
           ads:adUnitId="@string/banner_ad_unit_id" />

  • In the onCreate() method of the Activity, or the onCreateView() method of the Fragment, add the code to fetch the Ad:
MobileAds.initialize(getActivity().getApplicationContext(), 
                     getString(R.string.banner_ad_app_id));

AdView mAdView = (AdView) v.findViewById(R.id.adView);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest adRequest = builder.build();
mAdView.loadAd(adRequest);

  •  Note: I have tried to use builder.addKeyword() to retrieve targeting Ads. Unfortunately, this feature is not supported by Admob yet. And using builder.addKeyword() makes Ads rendering much slower.
 
Get This <