Thursday, May 13, 2021

ASUS N73 HDD Bracket/Caddy, 13GNZX1AM030-1 and 13GNZX10M10X-1 compatible

I had decided to install a second HDD in my ASUS N73, but I was missing a bracket for it. At that time there were no listings on eBay and that part was really hard to obtain. My improvised solutions weren't good enough and disk drive would sometimes get disconnected. It is a laptop anyway that you flip and carry around.

So, I've decided to make my own extra bracket. I took a caliper, measured the original bracket and modeled it in FreeCAD

The first bracket prototype was made on a 3D printer. I never thought that the plastic that thin will be strong enough to hold a HDD (of course it did not!), but I wanted to check is my model OK and make sure that everything does fit. The 'legs' broke right away and plastic shrank as it cooled so that experiment wasn't much of a success.

Obviously, a bracket that thin (0.55 mm) would be the best made of steel. I started to look for manufactures in China and soon enough I've found a company that offered to send me a free sample made in Cold Rolled Steel Plate technique.

If you need similar products in bigger quantity, you can reach them at:

JM FCX Metal Industrial Co., Ltd.
Chaolian Industrial Area, Jiangmen city, GD., P.R China
Tel: 0086-750-2037012
0086-189-2308-8730 (WhatsApp, Wechat)

If you are looking  for CAD files (iges, stl and FCStd formats) for the bracket, you can download them from here.

Monday, May 3, 2021

How NOT TO get banned from AdMob for 'click fraud'

  1. During development: use the test ad unit id. 
  2. For release: add test device(s) to your AdMob account.

As simple as that. In more details:

1. During development: use test ad unit id

Following  the AdMob integration instructions, you will be provided with the test ad unit id. Obviously, you will not hard-code it in your app, you will access it just like any other string resource - via Activity.getString method.

The example might be the following:

String    adId      = getString(R.string.ad_unit_id);
AdRequest adRequest = new AdRequest.Builder().build();

RewardedInterstitialAd.load(this, adId, adRequest,
new RewardedInterstitialAdLoadCallback() { ... });

Here I am creating a rewarded interstitial ad, but principle is the same for any other type of ads - banner, interstitial or native. 

Now we will place the given test ad unit id in a resource file, donottranslate.xml being an ideal candidate for that:

<?xml version="1.0" encoding="utf-8"?>
<string name="ad_unit_id">ca-app-pub-xxxxxxxxxxxxxxxx/x...</string>

Instead of placing this file in /src/main/res/values folder we'll put it in /src/debug/res/values (create it if it doesn't exist). 

This string resource will now exist only when we are building a debug version of our app, so we need to do the similar thing for a release version. We will create the folder (path) /src/release/res/values and we will put another donottranslate.xml file inside. This file will look exactly the same as the previous one, except that you will replace the test ad unit id with the real one that you got when you have created an ad. Your project structure should look something like this:

We're done regarding this part! Our debug builds will use the test ad and release builds the real one. Now let's get ourselves covered and make sure that we are not shown a real ad when we are testing a release build on our device(s).

2. For release: add test device(s) to your AdMob account

Once you are logged in your AdMob account, on the left hand side, close to the bottom of the navigation bar, open Settings and then Test Devices tab. Click on the Add Test Device button and fill out the form. Voila!


This blog post was inspired by the following blog post: Never run Google ads if you have an Android app, especially by its subtitle: Google can and will permanently ban your Android app if Google thinks you’ve clicked on your own ads. This does not need to happen and, as it has been shown, accident of clicking (or even watching) your own ads can be easily prevented.

Thursday, April 15, 2021

CORS header 'Access-Control-Allow-Origin' missing and Java Servlet

 As it is answered here, HttpServlet.doOptions() method has to be overridden the following way:


import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

    name = "MyServlet",
    urlPatterns = {"/myservlet"}
public class MyServlet extends HttpServlet {
    protected void doOptions
HttpServletRequest req,
            HttpServletResponse resp
        )         throws IOException {         resp.setHeader("Access-Control-Allow-Origin", "*");      resp.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");      resp.setHeader("Access-Control-Allow-Headers", "*");     }     @Override     protected void doPost
            HttpServletRequest req,
            HttpServletResponse resp
        )         throws IOException {         resp.setHeader("Access-Control-Allow-Origin", "*");         resp.setContentType("text/plain");         resp.setCharacterEncoding("UTF-8");         resp.getOutputStream().println("OK");     }     @Override     protected void doGet
            HttpServletRequest req,
            HttpServletResponse resp
        )         throws IOException {         doPost(req, resp);     } }

Sunday, April 11, 2021

Covid19 Travel Information - updated daily

Another web project finished. This time daily updated corona virus related travel information at:

Covid19 Travel Information

HTML, javascript without any frameworks, only Papa Parse for CSV parsing and python for data processing. Data is fetched from The Humanitarian Data Exchange. There is no database at all and site is hosted on GitHub Pages!

Covid19 Bar Chart Race

I got bored watching 'ordinary' corona virus charts, I couldn't find updated bar chart race, so I made it myself. A small weekend project at:

Covid19 Bar Chart Race

Data comes from The Humanitarian Data Exchange, it is processed with python and Flourish is used for visualization. Unfortunately, automatic data upload is available in their business plans only, so there is one manual step left to. Hosted on GitHub Pages!

Saturday, April 3, 2021

NOAA API web servers rejecting Android app requests (error code 403)

Probably it is a NOAA's (National Oceanic and Atmospheric Administration) response to problems outlined in this article: Weather Service Internet systems are crumbling as key platforms are taxed and failing.

HTTP(S) requests to servers made from Android apps (that are using default User-Agent header) are failing with error code - 403 Forbidden. Not sure exactly since when, and not sure what User-Agent headers are blocked, in my case it was a testing device with:

"Dalvik/2.1.0 (Linux; U; Android 5.0.2; Android SDK built for x86_64 Build/LSY66K)"

 The solution is pretty simple, you have to make request with User-Agent header set as described in this Stack Overflow answer

Monday, December 28, 2020

PayPal Europe VAT number is LU22046007

The bigger they are (and the more we depend on them), the more their customer support sucks. There is no way you will find out this data by contacting them through the available channels, so here it is for all desperate people who need it for their accounting purposes. I am throwing in some extra contact data as I am feeling extra inspired by PayPal's cooperativeness. 

P.S: Don't forget that starting from December 16, 2020 European PayPal accounts are charged an inactivity service fee (if you have no activity in previous 12 months) that is €10 EUR. I am moving my business away from them.

Full address:
PayPal Europe S.a.r.l. & Cie, S.C.A.
5th Floor
22-24, Boulevard Royal L-2449

Administrative & financial information:
International VAT number : LU22046007
Nace : Sociétés de participation financière (Soparfi) (64202)
Trade registry No. : B127485
Capital : 2 200 000 €
Number of employees : 200
Date of creation : 04/2007

Phone numbers:
+352 26 63 91 00   Mr. Paul Marriott-Clarke (CEO)
+352 27 85 88 27
+352 26 11 53 399 
 +352 26 63 92 50

Email address: