fatal error: ‘liblights/samsung_lights_helper.h’ file not found

Moving on from the S4, I began work on the Note Edge, only to be greeted with this error:

[CODE]
target thumb C: lights.APQ8084 <= hardware/samsung/liblights/lights.c
hardware/samsung/liblights/lights.c:34:10: fatal error: ‘liblights/samsung_lights_helper.h’ file not found
#include <liblights/samsung_lights_helper.h>
^
1 error generated.
[/CODE]

The fix was easy enough, I checked the folder, and sure enough, it was not there. So, I downloaded it from here:

https://github.com/LineageOS/android_hardware_samsung/tree/310d1999e5478a28b73eacbc5b4db62174431ee9/liblights

I like simple problems!

Linux – keep it simple.

Yet again, error: package com.android.okhttp does not exist

By now, I think I would remember this one by heart, yet every time, this error throws me for a loop….

[CODE]
external/apache-http/../../frameworks/base/core/java/android/net/http/SslCertificate.java:19: error: cannot find symbol
import com.android.internal.util.HexDump;
^
symbol: class HexDump
location: package com.android.internal.util
external/apache-http/../../frameworks/base/core/java/android/net/http/SslCertificate.java:42: error: package com.android.org.bouncycastle.asn1.x509 does not exist
import com.android.org.bouncycastle.asn1.x509.X509Name;
^
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:19: error: package com.android.okhttp does not exist
import com.android.okhttp.Cache;
^
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:20: error: package com.android.okhttp does not exist
import com.android.okhttp.AndroidShimResponseCache;
^
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:21: error: package com.android.okhttp does not exist
import com.android.okhttp.OkCacheContainer;
^
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:152: error: cannot find symbol
public final class HttpResponseCache extends ResponseCache implements Closeable, OkCacheContainer {/home/alaskalinuxuser/compile/20170314_AOKP7/prebuilts/tools/common/m2/repository/com/squareup/okhttp/okhttp/2.5.0
^
symbol: class OkCacheContainer
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:154: error: cannot find symbol
private final AndroidShimResponseCache delegate;
^
symbol: class AndroidShimResponseCache
location: class HttpResponseCache
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:156: error: cannot find symbol
private HttpResponseCache(AndroidShimResponseCache delegate) {
^
symbol: class AndroidShimResponseCache
location: class HttpResponseCache
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:296: error: cannot find symbol
public Cache getCache() {
^
symbol: class Cache
location: class HttpResponseCache
[/CODE]

And, from the same website that I fail to bookmark every time:

https://issuetracker.google.com/issues/37130763

These are caused by missing some package dependency. Following patch is used to fix it (for external/apache-http/Android.mk):

— a/Android.mk
+++ b/Android.mk
@@ -95,7 +95,7 @@ LOCAL_SRC_FILES += \
../../frameworks/base/core/java/android/net/http/SslError.java \

-LOCAL_JAVA_LIBRARIES := $(apache_http_java_libs)
+LOCAL_JAVA_LIBRARIES := $(apache_http_java_libs) okhttp bouncycastle framework
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src \
$(LOCAL_PATH)/android \

That’s it. Those few ines make the whole thing work. Hopefully, I’m saving someone else from scouring the internet for this problem. Again.

Linux – keep it simple.

SyntaxError: invalid syntax

As I was wrapping up my work on the upgrade to 7.1.2 on the S4, I ran into this error, which prevented the compiler from building the userdata.img file. Here’s the output:

[CODE]
get/product/jfltetmo/userdata.img
File “./build/tools/releasetools/build_image.py”, line 157
print cmd
^
SyntaxError: invalid syntax
[/CODE]

The fix was actually quite easy. I needed to encapsulate the cmd in parenthesis, like this:

./build/tools/releasetools/build_image.py

[CODE]
cmd = “fec -e -p %d %s %s %s” % (padding_size, sparse_image_path,
verity_path, verity_fec_path)
print (cmd) # WJH
status, output = commands.getstatusoutput(cmd)
[/CODE]

The proof is in the pudding, but what help was how the cmd is defined, then notice that the “status, output” line also puts cmd in parenthesis. So, I did the same for the print cmd line, and it worked!

Linux – keep it simple.

Healthd problems with pointers to fonts….

In the continuing saga of updating to 7.1.2, I’ve run into an interesting error about gr_text and gr_measure that are used to set the fonts properly when you are charging your phone while it is off. In 7.1.1, this worked just fine:

AOKP711/system/core/healthd/healthd_mode_charger.cpp

[CODE]
static int draw_text(const char *str, int x, int y)
{
int str_len_px = gr_measure(str);

if (x < 0)
x = (gr_fb_width() – str_len_px) / 2;
if (y < 0)
y = (gr_fb_height() – char_height) / 2;
gr_text(x, y, str, 0);

return y + char_height;
———- Abreviated for space ——————–
gr_init();
gr_font_size(&char_width, &char_height);

#ifndef CHARGER_DISABLE_INIT_BLANK
[/CODE]

But that didn’t work in 7.1.2. I found this github commit for a sony phone: https://github.com/sonyxperiadev/device-sony-common/pull/247 and was able to modify it enough to fix the S4, like so:

AOKP712/system/core/healthd/healthd_mode_charger.cpp

[CODE]
static int draw_text(const char *str, int x, int y)
{
int str_len_px = gr_measure(gr_sys_font(), str); // WJH

if (x < 0)
x = (gr_fb_width() – str_len_px) / 2;
if (y < 0)
y = (gr_fb_height() – char_height) / 2;
gr_text(gr_sys_font(), x, y, str, 0); // WJH

return y + char_height;
———- Abreviated for space ——————–
gr_init();
gr_font_size(gr_sys_font(), &char_width, &char_height); //WJH

#ifndef CHARGER_DISABLE_INIT_BLANK
[/CODE]

It even worked! Hopefully that can help someone else out as well.

Linux – keep it simple.

 

CID_PATH not defined!

In an attempt to update the AOKP 7.1.1 rom for the Samsung Galaxy S4 to 7.1.2, I received an error about AOKP712/hardware/libhardware_legacy/wifi/wifi.c:179.18. The error complained that the CID_PATH was not defined, declared, or was not known.

Obviously, it was supposed to be declared somewhere, and I had two choices, declare it, or replace it with the actual path. I did the latter. Here is the old file:

[CODE]
#ifdef SAMSUNG_WIFI
char* get_samsung_wifi_type()
{
char buf[10];
int fd = open(CID_PATH, O_RDONLY);
if (fd < 0)
return NULL;
[/CODE]

And here is the new file changes:

[CODE]
#ifdef SAMSUNG_WIFI
char* get_samsung_wifi_type()
{
char buf[10];
int fd = open(“/data/.cid.info”, O_RDONLY); // WJH
if (fd < 0)
return NULL;
[/CODE]

And, to God be the glory, it works! One error down, only dozens to go!

Linux – keep it simple.

WebViews for dummies like me.

In my Android Developer Course, the instructor showed us how to create webviews and dataviews. I wanted to take that one step farther, so I made this app, which can switch between a dataview and a webview. You can download it here, just click on the floating button to switch between the views:

http://www.mediafire.com/file/d8x9yc4ykn7943v/Webviewfordummieslikeme.apk

Currently, for a webview, it goes to my website, right here. For a data view, I just threw together a few lines of HTML code and slapped it in there. But, here are a few great little tidbits about the program for those who are new like me, and need help figuring out what to do.

MainActivity.java

/* Copyright 2017 by AlaskaLinuxUser (https://thealaskalinuxuser.wordpress.com)
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alaskalinuxuser.webviewsfordummies;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

// Declare your webview …
WebView myWebView;
// Declare our boolean for switching.
Boolean webViewTrue;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

// Set our boolean to true, as we are displaying a website first.
webViewTrue = true;

// To identify my webview that I am going to put the website or data on.
myWebView = (WebView)findViewById(R.id.myWebView);

// To enable javascript.
myWebView.getSettings().setJavaScriptEnabled(true);

// To keep it here in our mini webview browser
myWebView.setWebViewClient(new WebViewClient());

// To load which webpage, in this case, mine.
myWebView.loadUrl(“https://thealaskalinuxuser.wordpress.com&#8221;);

// So, by clicking on the FAB, you can swap between webview and dataview.
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, “Switched between webview and dataview.”, Snackbar.LENGTH_LONG)
.setAction(“Action”, null).show();

// If we are in webview mode.
if (webViewTrue) {

// Then switch to dataview mode.
webViewTrue = false;

// You can load any data you make, you just need data, type, and encoding.
String myEncoding = “UTF-8”;
String myType = “text/html”;
String myData = “<html><body><h1>Check this out!</h1><p>This is just demonstrating how to load your own ‘data’.</p><h2>More info!</h2><p>Feel free to test this out with some code edits.</p></body></html>”;

// And pass that to our webview.
myWebView.loadData(myData, myType, myEncoding);

// Else, if you are in dataview, switch to web view.
} else {

// Set our boolean back to true.
webViewTrue = true;

// To load which webpage, in this case, mine.
myWebView.loadUrl(“https://thealaskalinuxuser.wordpress.com&#8221;);

}

}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}
The key parts here are these:

// If we are in webview mode.
if (webViewTrue) {

// Then switch to dataview mode.
webViewTrue = false;

// You can load any data you make, you just need data, type, and encoding.
String myEncoding = “UTF-8”;
String myType = “text/html”;
String myData = “<html><body><h1>Check this out!</h1><p>This is just demonstrating how to load your own ‘data’.</p><h2>More info!</h2><p>Feel free to test this out with some code edits.</p></body></html>”;

// And pass that to our webview.
myWebView.loadData(myData, myType, myEncoding);

// Else, if you are in dataview, switch to web view.
} else {

// Set our boolean back to true.
webViewTrue = true;

// To load which webpage, in this case, mine.
myWebView.loadUrl(“https://thealaskalinuxuser.wordpress.com&#8221;);

}

If you are in a webview, it switches to a dataview, and vice versa. But the thing I wanted to point out is the use of the String variables (myEncoding, myType, myData) which here I just set statically, but you could have some app that when the user clicks something, it fills in these variables, which in turn, when you load the data, it now has some pertinent information. Just food for thought. Praise God, it even works!

Linux – keep it simple.

An easy way to double check your SQLlite syntax

While in the Android Developer Course, I am finding a little problem with using SQLlite. In Android Studio, when writing Java, Android Studio knows when the code you typed has an error, and it underlines it in red, showing you something you should fix.

However, when you are using SQLlite in your java code. Android Studio has no idea what you are talking about. This causes me a bit of heartburn as I run my apps only to find that something is wrong with my SQL code, but no idea of what to fix.

Thus enter https://sqliteonline.com/ ! I can copy and paste syntax into the web gui and give it a quick run to see if it even works. It has been most helpful to say the least. If you are just starting out with SQLlite, I highly recommend it over other web gui interfaces for testing, because it has a simple display on the left side, showing you all of your tables, views, indexes, and triggers. For a simpleton like me, that is really helpful to have a visual representation.

Linux – keep it simple.

Using SQLlite in your Android app

So, as part of my Android Developer Course by Rob Percival (which is excellent, and I highly recommend every computer/Android geek take), he showed us how to make use of SQLlite in our Android app. In the demonstration and challenge, he was using static inputs, like this:
// And add some information to that table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘Birth’, 1985)”);

Which is great. He was just showing us how SQLlite worked. With that said, in a really useful app, I figured I would need a way to take a user’s input and put it into the table, so I fiddled around a bit, and here is what I came up with.

MainActivity.java:
/* Copyright 2017 by AlaskaLinuxUser (https://thealaskalinuxuser.wordpress.com)
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alaskalinuxuser.sqllitedemo;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Let’s make some variables to use later.
String nameVar = “Joined the Navy”;
int yearVar = 2004;

try {

// First, make a database, open or create will open if exist, create if not.
SQLiteDatabase firstDatabaseEver = this.openOrCreateDatabase(“events”, MODE_PRIVATE, null);

// Now, let’s ceate a table.
firstDatabaseEver.execSQL(“CREATE TABLE IF NOT EXISTS events (name VARCHAR, year INT(4))”);

// And add some information to that table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘Birth’, 1985)”);

// And a second one for fun, this time, we will use our variable we created, you can see
// how this would be useful for an app, so you could have the user’s input dumped into a
// table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘” + nameVar + “‘, ” + yearVar + “)”);

// Now we need a cursor to retreive the data with a query.
Cursor myCursor = firstDatabaseEver.rawQuery(“SELECT * FROM events”, null);

// Now that we have the data, we need a way to index them, or grab the parts we need.
int nameIndex = myCursor.getColumnIndex(“name”);
int yearIndex = myCursor.getColumnIndex(“year”);

// Let’s start from the top of the table, by moving to the first position.
myCursor.moveToFirst();

// And if it is not null, let’s use it.
while (myCursor != null){

// Logging for posterity….
Log.i(“WJH”, myCursor.getString(nameIndex));
Log.i(“WJH”, Integer.toString(myCursor.getInt(yearIndex)));

// And move on to the next result in the table.
myCursor.moveToNext();
}
} catch (Exception e) {

e.printStackTrace();

}
}
}

Note that I don’t actually have user’s input into the table here, but I did use variables to input the data into the table, like so:

// Let’s make some variables to use later.
String nameVar = “Joined the Navy”;
int yearVar = 2004;

// And a second one for fun, this time, we will use our variable we created, you can see
// how this would be useful for an app, so you could have the user’s input dumped into a
// table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘” + nameVar + “‘, ” + yearVar + “)”);

As we can see, the input into the table of “events” is based on the output of the variables “nameVar and yearVar, which I previously defined. It is really easy to see that we could use something like getText from an editText field and input those variables into the tables. Which I think is the best use of it.

Linux – keep it simple.