I'm working on an android app and I'm trying to plugin-like feature which would allow loading additional dex files to extend app functionality. I've figured out how to load additional dex files extending PathClassLoader with few small changes to allow other modules to communicate. The issue is that when the dex files are loaded into the app for the first time when the app is running all works perfectly, then if I decide to disable this module so the classloader is unloaded the app continues to work properly for a few seconds then it throws exception (still continue working properly) and then again few seconds/minutes later (sometimes it takes even 5 minutes) the app crashes with native stack trace. If I decide to load the module which I disabled previously again it will only increase a chance to crash.
This is what happens few seconds module classloader is unloaded:
12-27 01:57:10.839 E/System: Uncaught exception thrown by finalizer
12-27 01:57:10.840 E/System: java.lang.AssertionError: Failed to close dex file in finalizer.
at dalvik.system.DexFile.finalize(DexFile.java:336)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
at java.lang.Daemons$Daemon.run(Daemons.java:103)
at java.lang.Thread.run(Thread.java:764)
12-27 01:57:10.840 E/System: Uncaught exception thrown by finalizer
12-27 01:57:10.840 E/System: java.lang.AssertionError: Failed to close dex file in finalizer.
at dalvik.system.DexFile.finalize(DexFile.java:336)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
at java.lang.Daemons$Daemon.run(Daemons.java:103)
at java.lang.Thread.run(Thread.java:764)
12-27 01:57:10.841 E/System: Uncaught exception thrown by finalizer
12-27 01:57:10.841 E/System: java.lang.AssertionError: Failed to close dex file in finalizer.
at dalvik.system.DexFile.finalize(DexFile.java:336)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
at java.lang.Daemons$Daemon.run(Daemons.java:103)
at java.lang.Thread.run(Thread.java:764)
Then few seconds or minutes later there is native crash:
12-27 01:57:15.409 A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
12-27 01:57:15.409 A/DEBUG: Build fingerprint: 'Sony/G8341/G8341:8.0.0/47.1.A.8.49/3744219090:user/release-keys'
12-27 01:57:15.409 A/DEBUG: Revision: '0'
12-27 01:57:15.409 A/DEBUG: ABI: 'arm64'
12-27 01:57:15.409 A/DEBUG: pid: 17551, tid: 17697, name: Profile Saver >>> com.rowl.plugdj
12-27 01:57:15.409 A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x657a6983
12-27 01:57:15.409 A/DEBUG: x0 00000000657a6973 x1 0000007bb0739460 x2 0000007bb0600000 x3 0000000000000002
12-27 01:57:15.409 A/DEBUG: x4 0000000000000139 x5 0000007bb073947f x6 2f6d65747379732f x7 726f77656d617266
12-27 01:57:15.409 A/DEBUG: x8 0000000013954588 x9 aec629c3012f5dc2 x10 0000000000000139 x11 000000000000004c
12-27 01:57:15.409 A/DEBUG: x12 656d6172662f6b72 x13 72616a2e6b726f77 x14 000000000000000d x15 aaaaaaaaaaaaaaab
12-27 01:57:15.409 A/DEBUG: x16 0000007bca457cc8 x17 0000007bca3f5f60 x18 0000007bc9c07eb0 x19 0000007baecba270
12-27 01:57:15.409 A/DEBUG: x20 0000007ba6ab68c0 x21 0000007baecba588 x22 0000007ba6ab4298 x23 0000007baa692b18
12-27 01:57:15.409 A/DEBUG: x24 0000000000000000 x25 0000000000002710 x26 00000000977434b0 x27 0000000097746934
12-27 01:57:15.409 A/DEBUG: x28 0000007bc99b6b70 x29 0000007baecba1d0 x30 0000007bc96cf67c
12-27 01:57:15.409 A/DEBUG: sp 0000007baecba0c0 pc 0000007bc96cf634 pstate 0000000080000000
12-27 01:57:15.411 A/DEBUG: backtrace:
12-27 01:57:15.411 A/DEBUG: #00 pc 00000000002fe634 /system/lib64/libart.so (_ZN3art3jit12JitCodeCache18GetProfiledMethodsERKNSt3__13setINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_4lessIS9_EENS7_IS9_EEEERNS2_6vectorINS_17ProfileMethodInfoENS7_ISH_EEEE+228)
12-27 01:57:15.411 A/DEBUG: #01 pc 000000000030ac08 /system/lib64/libart.so (_ZN3art12ProfileSaver20ProcessProfilingInfoEbPt+1452)
12-27 01:57:15.411 A/DEBUG: #02 pc 00000000003099ac /system/lib64/libart.so (_ZN3art12ProfileSaver3RunEv+704)
12-27 01:57:15.411 A/DEBUG: #03 pc 000000000030b7b8 /system/lib64/libart.so (_ZN3art12ProfileSaver21RunProfileSaverThreadEPv+88)
12-27 01:57:15.411 A/DEBUG: #04 pc 00000000000667d0 /system/lib64/libc.so (_ZL15__pthread_startPv+36)
12-27 01:57:15.411 A/DEBUG: #05 pc 000000000001f2a4 /system/lib64/libc.so (__start_thread+68)
Here is the classloader which I'm using
public class ExtensionClassLoader extends PathClassLoader {
private final Map<String, Class<?>> classes = new HashMap();
private final ExtensionManager extensionManager;
public ExtensionClassLoader(ExtensionManager extensionManager, String dexPath, String librarySearchPath, ClassLoader parent) {
super(dexPath, librarySearchPath, parent);
this.extensionManager = extensionManager;
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (name.startsWith("com.rowl.") || name.startsWith("dj.plug.")) {
throw new ClassNotFoundException(name);
}
PlugDJ.d("Find Class: " + name);
Class clazz = classes.get(name);
if(clazz == null){
clazz = extensionManager.getClass(name);
if(clazz == null){
clazz = super.findClass(name);
if(clazz != null){
extensionManager.addClass(name, clazz);
}
}
if(clazz != null){
classes.put(name, clazz);
}
}
return clazz;
}
#Override
public String findLibrary(String name) {
return super.findLibrary(name);
}
public Set<String> getClasses(){
return classes.keySet();
}
#Override
protected void finalize() throws Throwable {
super.finalize();
}
}
Additionally here is the class which loads these modules:
class ExtensionManager(plugDJInstance: PlugDJ) : Manager(plugDJInstance) {
private val classes = HashMap<String, Class<*>>()
private val extensionLoaders = HashMap<String, ExtensionClassLoader>()
private val loadedExtensions = ArrayList<PDJExtension>()
private val availableExtensions = ArrayList<PDJExtensionInfo>()
val plugAPI = PlugAPIImpl(pdjInstance as PlugDJAndroid)
private val context by lazy { (pdjInstance as PlugDJAndroid).context }
private val extensionSettings by lazy { context.getSharedPreferences("ext", Context.MODE_PRIVATE)}
private val whitelistedExtensions by lazy { extensionSettings.getStringSet("whitelistedExtensions", HashSet<String>()) }
fun addClass(name: String, clazz: Class<*>){
if(!classes.containsKey(name)){
classes.put(name, clazz)
}
}
fun removeClass(name: String){
classes.remove(name)
}
fun getClass(name: String): Class<*>?{
return classes[name]
}
private fun loadApk(dir: File, dexOutputDir: File, parent: ClassLoader): ExtensionClassLoader{
val files = StringBuilder()
dir.listFiles().filter { it.extension == "apk" }.forEach {
files.append(it.absolutePath).append(":")
}
files.deleteCharAt(files.length - 1)
return ExtensionClassLoader(this, files.toString(), dexOutputDir.absolutePath.toString(), parent)
}
fun isExtensionWhitelisted(extInfo: PDJExtensionInfo): Boolean{
return whitelistedExtensions.contains(extInfo.appPackage)
}
#SuppressLint("ApplySharedPref")
fun addExtensionToWhitelist(extInfo: PDJExtensionInfo){
whitelistedExtensions.add(extInfo.appPackage)
extensionSettings.edit().putStringSet("whitelistedExtensions", whitelistedExtensions).commit()
d("Added " + extInfo.appPackage + " to whitelist")
}
#SuppressLint("ApplySharedPref")
fun removeExtensionFromWhitelist(extInfo: PDJExtensionInfo){
whitelistedExtensions.remove(extInfo.appPackage)
extensionSettings.edit().putStringSet("whitelistedExtensions", if(whitelistedExtensions.isEmpty()) null else whitelistedExtensions).commit()
d("Checking... " + whitelistedExtensions)
d("Removed " + extInfo.appPackage + " from whitelist")
}
fun discoverExtensions() {
try{
whitelistedExtensions.forEach {
d("Whitelisted extension: $it")
}
val installedApps = context.packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
for(app in installedApps){
if(app.sourceDir.contains("system")) continue
if(app.metaData != null && app.metaData.containsKey("pdjExtensionName")){
val extName = app.metaData.getString("pdjExtensionName")
val extMainClass = app.metaData.getString("pdjExtensionMainClass")
val sourceDir = File(app.sourceDir).parentFile
PlugDJ.i("Found extension: " + extName)
var extInfo = getAvailableExtensions().find { it.appPackage == app.packageName }
d(extInfo?.sourceDirectory.toString() )
d(sourceDir.toString() )
if(extInfo != null){
PlugDJ.d("Removing " + app.packageName)
availableExtensions.remove(extInfo)
}
extInfo = PDJExtensionInfoImpl(extName, sourceDir, app.packageName, extMainClass, "", "", null, null)
availableExtensions.add(extInfo)
}
}
}catch (e: Exception){
e.printStackTrace()
}
}
fun getAvailableExtensions(): List<PDJExtensionInfo>{
return Collections.unmodifiableList(ArrayList(availableExtensions))
}
fun getLoadedExtensions(): List<PDJExtension>{
return Collections.unmodifiableList(ArrayList(loadedExtensions))
}
fun loadExtension(extInfo: PDJExtensionInfo): PDJExtension{
var cl = context.classLoader
val dexOutputDir = context.getDir("dex", Context.MODE_PRIVATE)
val extcl = loadApk(extInfo.sourceDirectory, dexOutputDir, cl)
extensionLoaders[extInfo.name] = extcl
val mainClass = extcl.loadClass(extInfo.mainClass)
val apiField = mainClass.superclass.getDeclaredField("api")
val clField = mainClass.superclass.getDeclaredField("classLoader")
val extField = mainClass.superclass.getDeclaredField("extensionInfo")
val extension = mainClass.newInstance() as PDJExtension
apiField.apply {
isAccessible = true
set(extension, plugAPI)
isAccessible = false
}
clField.apply {
isAccessible = true
set(extension, mainClass.classLoader)
isAccessible = false
}
extField.apply {
isAccessible = true
set(extension, extInfo)
isAccessible = false
}
loadedExtensions.add(extension)
return extension
}
fun getLoadedExtension(appPackage: String): PDJExtension? {
return getLoadedExtensions().find { it.extensionInfo.appPackage == appPackage }
}
fun enableExtension(ext: PDJExtension){
ext.onEnable()
ext::class.java.superclass.getDeclaredField("isEnabled").apply {
isAccessible = true
set(ext, true)
isAccessible = false
}
}
fun disableExtension(ext: PDJExtension){
try{
plugAPI.removeEventListeners(ext)
ext.onDisable()
}catch (e: Exception){
e.printStackTrace()
}
ext::class.java.superclass.getDeclaredField("isEnabled").apply {
isAccessible = true
set(ext, false)
isAccessible = false
}
}
fun unloadExtension(ext: PDJExtension){
d("Unloading extension...")
ext::class.java.superclass.getDeclaredField("api").apply {
isAccessible = true
set(ext, null)
isAccessible = false
}
val cl = ext.classLoader as ExtensionClassLoader
loadedExtensions.remove(ext)
for(className in cl.classes){
removeClass(className)
}
extensionLoaders.remove(ext.extensionInfo.name)
d("Extension unloaded.")
System.runFinalization()
System.gc()
}
}
Additionally, here is the full log https://pastebin.com/Jhpk4Wpc
Any idea what causes it?
Make sure you are not deleting the dex file.
Related
I am using the following code to refresh the weather information on the display of the phone, it worked great the first 2 - 3 times but after that it started crashing and giving me this error.
Here is the code:
package com.example.ma18uus.myapplication;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
public class weatherView extends AppCompatActivity {
//Main url
static final String main_url = "http://api.weatherapi.com/v1/";
//Live or Weekly forecast
static final String live_weather = "current.xml?key=";
//String sevendays_weather = "orecast.xml?key=";
//API Key + q
static final String API_Key = "c3bdfadb90d5452bb8003318201801&q=";
//Location Setters
static final String location = "London";
//Complete url for todays forecast
static final String URLT = main_url + live_weather + API_Key + location;
//XML node keys
static final String KEY_ITEM = "root";//parent node
static final String KEY_NAME = "name";//name of city, string
static final String KEY_WIND_MPH = "wind_mph";//wind mph, float
static final String KEY_WIND_KPH = "wind_kph";//wind kph, float
static final String KEY_C = "temp_c";//Temperature Celsius, int
static final String KEY_C_FEELS = "feelslike_c";//Temperature feeling Celsius, float
static final String KEY_F = "temp_f";//Temperature Fahrenheit, int
static final String KEY_F_FEELS = "feelslike_f";//Temperature feeling Fahrenheit, float
static final String KEY_HUMIDITY = "humidity";//Humidity Level, int
static final String KEY_CONDITION_TEXT = "text";//Weather Condition i.e. cloudy, sunny, clear, string
ArrayList<HashMap<String, String>> menuItems;
private TextView txt;
String xml;
//#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather_view);
menuItems = new ArrayList<HashMap<String, String>>();
txt = (TextView) findViewById(R.id.weather_window);
new weatherTask().execute();
// weatherTask.parseXML();
}
private class weatherTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... voids) {
parseXML();
return null;
}
private void parseXML(){
XmlPullParserFactory parserFactory;
try {
parserFactory = XmlPullParserFactory.newInstance();
XmlPullParser parser = parserFactory.newPullParser();
try {
InputStream is = new URL(URLT).openStream();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, null);
processParsing(parser);
} catch (IOException e) {
e.printStackTrace();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
private void processParsing(XmlPullParser parser) throws IOException, XmlPullParserException{
ArrayList<WeatherConditions> weather = new ArrayList<>();
int eventType = parser.getEventType();
WeatherConditions currentWeather = null;
while(eventType != XmlPullParser.END_DOCUMENT){
String sName = null;
switch(eventType){
case XmlPullParser.START_TAG:
sName = parser.getName();
if ("root".equals(sName)){
currentWeather = new WeatherConditions();
weather.add(currentWeather);
}else if (currentWeather != null){
if ("name".equals(sName)){
currentWeather.name = parser.nextText();
}
else if ("wind_mph".equals(sName)){
currentWeather.wind_mph = parser.nextText();
}else if ("wind_kph".equals(sName)){
currentWeather.wind_kph = parser.nextText();
}else if ("temp_c".equals(sName)){
currentWeather.celsius = parser.nextText();
}else if ("feelsCelsius".equals(sName)){
currentWeather.feelsCelsius = parser.nextText();
}else if ("fahrenheit".equals(sName)){
currentWeather.fahrenheit = parser.nextText();
}else if ("feelsFahrenheit".equals(sName)){
currentWeather.feelsFahrenheit = parser.nextText();
}else if ("humidity".equals(sName)){
currentWeather.humidity = parser.nextText();
}else if ("text".equals(sName)){
currentWeather.condition_text = parser.nextText();
}
}
break;
}
eventType = parser.next();
}
printWeather(weather);
}
private void printWeather(ArrayList<WeatherConditions> weather){
StringBuilder builder = new StringBuilder();
for (WeatherConditions weatherC : weather){
builder.append(weatherC.name).append("\n").append(weatherC.wind_mph).append("\n").append(weatherC.wind_kph).append("\n").append(weatherC.celsius).append("\n").append(weatherC.feelsCelsius).
append("\n").append(weatherC.fahrenheit).append("\n").append(weatherC.feelsFahrenheit).append("\n").append(weatherC.humidity).append("\n").append(weatherC.condition_text).append("\n");
}
txt.setText(builder.toString());
}
}
}
And here is the error output:
01/24 20:06:05: Launching 'app' on Pixel 2 API 29.
$ adb shell am start -n "com.example.ma18uus.myapplication/com.example.ma18uus.myapplication.ClothesApp" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Waiting for process to come online...
Connected to process 24573 on device 'emulator-5554'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/s.myapplicatio: The ClassLoaderContext is a special shared library.
D/libEGL: Emulator has host GPU support, qemu.gles is set to 1.
W/libc: Unable to set property "qemu.gles" to "1": connection failed; errno=13 (Permission denied)
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/RenderThread: type=1400 audit(0.0:300): avc: denied { write } for name="property_service" dev="tmpfs" ino=8445 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=0
W/s.myapplicatio: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
W/s.myapplicatio: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
D/HostConnection: HostConnection::get() New Host Connection established 0xdc973e60, tid 24609
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_gles_max_version_3_0
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 0 0
D/EGL_emulation: eglCreateContext: 0xe7fbaa20: maj 3 min 0 rcv 3
D/EGL_emulation: eglMakeCurrent: 0xe7fbaa20: ver 3 0 (tinfo 0xe7fe5b10)
W/Gralloc3: mapper 3.x is not supported
D/HostConnection: createUnique: call
HostConnection::get() New Host Connection established 0xdc975b70, tid 24609
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_gles_max_version_3_0
D/eglCodecCommon: allocate: Ask for block of size 0x1000
D/eglCodecCommon: allocate: ioctl allocate returned offset 0x3ff805000 size 0x2000
D/EGL_emulation: eglMakeCurrent: 0xe7fbaa20: ver 3 0 (tinfo 0xe7fe5b10)
D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 1 0
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy#8f4b1f9
D/NetworkSecurityConfig: Using Network Security Config from resource network_security_config debugBuild: true
D/EGL_emulation: eglMakeCurrent: 0xe7fbaa20: ver 3 0 (tinfo 0xe7fe5b10)
D/EGL_emulation: eglMakeCurrent: 0xe7fbaa20: ver 3 0 (tinfo 0xe7fe5b10)
D/EGL_emulation: eglMakeCurrent: 0xe7fbaa20: ver 3 0 (tinfo 0xe7fe5b10)
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.ma18uus.myapplication, PID: 24573
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:399)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8191)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1420)
at android.view.View.requestLayout(View.java:24454)
at android.view.View.requestLayout(View.java:24454)
at android.view.View.requestLayout(View.java:24454)
at android.view.View.requestLayout(View.java:24454)
at android.view.View.requestLayout(View.java:24454)
at android.view.View.requestLayout(View.java:24454)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:380)
at android.view.View.requestLayout(View.java:24454)
at android.widget.TextView.checkForRelayout(TextView.java:9681)
at android.widget.TextView.setText(TextView.java:6269)
at android.widget.TextView.setText(TextView.java:6097)
at android.widget.TextView.setText(TextView.java:6049)
at com.example.ma18uus.myapplication.weatherView$weatherTask.printWeather(weatherView.java:159)
at com.example.ma18uus.myapplication.weatherView$weatherTask.processParsing(weatherView.java:145)
at com.example.ma18uus.myapplication.weatherView$weatherTask.parseXML(weatherView.java:89)
at com.example.ma18uus.myapplication.weatherView$weatherTask.doInBackground(weatherView.java:73)
at com.example.ma18uus.myapplication.weatherView$weatherTask.doInBackground(weatherView.java:68)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
D/EGL_emulation: eglMakeCurrent: 0xe7fbaa20: ver 3 0 (tinfo 0xe7fe5b10)
I/Process: Sending signal. PID: 24573 SIG: 9
Process 24573 terminated.
The first time worked fine, then I changed celsius to temp_c, which is the name in the XML file and still worked fine. Then I changed feelsCelsius to feelslike_c which is the name in the XML file and the crash started and kept on happening even after getting the code back to the original state. I tried uninstalling and reinstalling the app as well, but nothing worked.
AsyncTask executes doInBackground() in the non-UI background thread. It cannot interact with the UI.
On the other hand, the onPostExecute method is allowed to touch UI as it's running in the main thread. So, refactor your AsyncTask to have result:
private class weatherTask extends AsyncTask<Void, Void, String> { // has result now
#Override
protected Void doInBackground(Void... voids) {
XmlPullParserFactory parserFactory;
try {
parserFactory = XmlPullParserFactory.newInstance();
XmlPullParser parser = parserFactory.newPullParser();
try {
InputStream is = new URL(URLT).openStream();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, null);
return processParsing(parser);
} catch (IOException e) {
e.printStackTrace();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
private String processParsing(XmlPullParser parser) throws IOException, XmlPullParserException{
ArrayList<WeatherConditions> weather = new ArrayList<>();
int eventType = parser.getEventType();
WeatherConditions currentWeather = null;
while(eventType != XmlPullParser.END_DOCUMENT){
String sName = null;
switch(eventType){
case XmlPullParser.START_TAG:
sName = parser.getName();
if ("root".equals(sName)){
currentWeather = new WeatherConditions();
weather.add(currentWeather);
}else if (currentWeather != null){
if ("name".equals(sName)){
currentWeather.name = parser.nextText();
}
else if ("wind_mph".equals(sName)){
currentWeather.wind_mph = parser.nextText();
}else if ("wind_kph".equals(sName)){
currentWeather.wind_kph = parser.nextText();
}else if ("temp_c".equals(sName)){
currentWeather.celsius = parser.nextText();
}else if ("feelsCelsius".equals(sName)){
currentWeather.feelsCelsius = parser.nextText();
}else if ("fahrenheit".equals(sName)){
currentWeather.fahrenheit = parser.nextText();
}else if ("feelsFahrenheit".equals(sName)){
currentWeather.feelsFahrenheit = parser.nextText();
}else if ("humidity".equals(sName)){
currentWeather.humidity = parser.nextText();
}else if ("text".equals(sName)){
currentWeather.condition_text = parser.nextText();
}
}
break;
}
eventType = parser.next();
}
return printWeather(weather);
}
private String printWeather(ArrayList<WeatherConditions> weather){
StringBuilder builder = new StringBuilder();
for (WeatherConditions weatherC : weather){
builder.append(weatherC.name).append("\n").append(weatherC.wind_mph).append("\n").append(weatherC.wind_kph).append("\n").append(weatherC.celsius).append("\n").append(weatherC.feelsCelsius).
append("\n").append(weatherC.fahrenheit).append("\n").append(weatherC.feelsFahrenheit).append("\n").append(weatherC.humidity).append("\n").append(weatherC.condition_text).append("\n");
}
return builder.toString();
}
/// THIS METHOD ADDED
#Override
protected void onPostExecute(String result) {
txt.setText(result);
}
}
I'm building an android application which first, users are register account with an id and then login where the system will checked if this user is using the same device as they use when registered. When the device are the same, then system will send a token to server. this is the method when checking the users device:
private void cekDataLogin(final String serial, final String device) throws IOException, JSONException {
#SuppressLint("StaticFieldLeak")
class dataLogin extends AsyncTask<Void, Void, String> {
private final WeakReference<MainActivity> mActivityRef;
private dataLogin(MainActivity activity) {
mActivityRef = new WeakReference<>(activity);
}
protected String doInBackground(Void[] params) {
String response = "";
HashMap<String, String> map = new HashMap<>();
try {
HttpRequest req = new HttpRequest(ipAddress + "/preserv/index.php?func=tokenget&ser=" + serial + "&dev=" + device);
response = req.prepare(HttpRequest.Method.GET).sendAndReadString();
} catch (Exception e) {
response = e.getMessage();
}
return response;
}
protected void onPostExecute(String result) {
onTaskCompletedPin(result, jsoncode);
}
}
new dataLogin(this).execute();
}
public void onTaskCompletedPin(String response, int serviceCode) {
Log.d("responsejson", response);
switch (serviceCode) {
case jsoncode:
try {
postDataToken();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
this is the method when sending new token:
private void postDataToken() throws IOException, JSONException {
final String android_id = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
final String token = SharedPreference.getInstance(MainActivity.this).getDeviceToken();
#SuppressLint("StaticFieldLeak")
class dataToken extends AsyncTask<Void, Void, String> {
private final WeakReference<MainActivity> mActivityRef;
private dataToken(MainActivity activity) {
mActivityRef = new WeakReference<>(activity);
}
protected String doInBackground(Void[] params) {
String response = "";
HashMap<String, String> map = new HashMap<>();
try {
HttpRequest req = new HttpRequest(ipAddress + "/preserv/index.php?func=devuptoken&ser=" + Build.SERIAL + "&dev=" + android_id + "&token=" + token);
response = req.prepare(HttpRequest.Method.POST).withData(map).sendAndReadString();
} catch (Exception e) {
response = e.getMessage();
}
return response;
}
protected void onPostExecute(String result) {
onTaskCompletedDevice(result, jsoncode);
}
}
new dataToken(this).execute();
}
public void onTaskCompletedDevice(String response, int serviceCode) {
Log.d("responsejson", response);
switch (serviceCode) {
case jsoncode:
if (response.contains("sukses")) {
final String android_id = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
if (KEY_CON.equalsIgnoreCase("Wifi")) {
if (ipAddress.contains("10.20.")) {
URL = "http://10.20.2.14/personal/index.php?serial=" + Build.SERIAL + "&device=" + android_id;
} else {
URL = "http://36.67.40.162:9024/personal/index.php?serial=" + Build.SERIAL + "&device=" + android_id;
}
} else {
URL = "http://36.67.40.162:9024/personal/index.php?serial=" + Build.SERIAL + "&device=" + android_id;
}
webView.loadUrl(URL);
} else if (response.contains("failed")) {
try {
postDataToken();
} catch (Exception e) {
toastMessage("Can't generate token");
}
} else {
toastMessage("ELSE");
}
}
}
and this resulting Unfortunately App has stopped and the error logcat look like this:
08-06 14:11:13.948 10722-10722/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.launcher.rsupsanglah.personalNotif, PID: 10722
java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:164)
at com.launcher.rsupsanglah.personal.MainActivity.m(Unknown Source)
at com.launcher.rsupsanglah.personal.MainActivity.a(Unknown Source)
at com.launcher.rsupsanglah.personal.MainActivity$a.a(Unknown Source)
at com.launcher.rsupsanglah.personal.MainActivity$a.onPostExecute(Unknown Source)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.
run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
08-06 14:11:14.013 3006-10804/? E/android.os.Debug: ro.product_ship = true
ro.debug_level = 0x4f4c
08-06 15:09:01.573 3006-3589/? V/ApplicationPolicy: isApplicationStateBlocked
userId 0 pkgname com.launcher.rsupsanglah.personalNotif
08-06 15:09:01.573 3006-3589/? W/ActivityManager: Force finishing activity
com.launcher.rsupsanglah.personalNotif/
com.launcher.rsupsanglah.personal.MainActivity
08-06 15:09:01.588 3006-27720/? W/DropBoxManagerService: Dropping:
data_app_crash (1228 > 0 bytes)
08-06 15:09:01.598 27618-27719/? I/FirebaseCrash: Sending crashes
08-06 15:09:01.603 27618-27719/? I/System.out: (HTTPLog)-Static:
isSBSettingEnabled false
08-06 15:09:01.633 3006-27722/? E/android.os.Debug: ro.product_ship = true
ro.debug_level = 0x4f4c
08-06 15:09:01.653 3006-3035/? D/StatusBarManagerService: manageDisableList
userId=0 what=0x0 pkg=WindowManager.LayoutParams
08-06 15:09:01.653 3006-3037/? D/PointerIcon: setMouseIconStyle1 pointerType:
1001iconType:101 flag:0
setMouseCustomIcon IconType is same.101
08-06 15:09:01.653 3006-3006/? D/CrashAnrDetector: NO DROPBOX ENTRY for
:data_app_crash 1533539341593
08-06 15:09:01.653 3006-3037/? D/PointerIcon: setHoveringSpenIconStyle1
pointerType: 10001iconType:1 flag:0
08-06 15:09:01.658 3006-3037/? D/PointerIcon: setHoveringSpenCustomIcon
IconType is same.1
08-06 15:09:01.663 2352-2352/? I/SurfaceFlinger: id=972 createSurf (49x49),1
flag=4, qersonalNot
08-06 15:09:01.663 21591-21591/? W/ContextImpl: Calling a method in the
system process without a qualified user:
android.app.ContextImpl.startService:2051
android.content.ContextWrapper.startService:533
android.content.ContextWrapper.startService:533
com.samsung.android.sm.common.SmartManagerReceiver.b:199
com.samsung.android.sm.common.SmartManagerReceiver.onReceive:93
08-06 15:09:01.663 3006-3449/? D/ActivityManager: startService
callerProcessName:com.samsung.android.sm, calleePkgName:
com.samsung.android.sm
caller:android.app.ApplicationThreadProxy#18ebc41, r.packageName
:com.samsung.android.sm
08-06 15:09:01.673 3006-3585/? D/ActivityManager:
caller:android.app.ApplicationThreadProxy#37c86727, r.packageName
:com.google.android.gms
08-06 15:09:01.683 3006-4255/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
caller:android.app.ApplicationThreadProxy#17c9db7d, r.packageName
:com.google.android.gms
08-06 15:09:01.683 3006-3175/? I/OpenGLRenderer: Initialized EGL, version 1.4
08-06 15:09:01.693 3006-3449/? D/ActivityManager: bindService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms, action:
com.google.android.gms.phenotype.service.START
08-06 15:09:01.703 3006-3175/? I/OpenGLRenderer: HWUI protection enabled for
context , &this =0x9e959f88 ,&mEglDisplay = 1 , &mEglConfig = -1641421900
08-06 15:09:01.703 3006-3019/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
08-06 15:09:01.708 3006-3019/? D/ActivityManager:
caller:android.app.ApplicationThreadProxy#7a9336c, r.packageName
:com.google.android.gms
08-06 15:09:01.723 3006-3587/? D/ActivityManager: bindService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms, action: com.google.android.gms.clearcut.service.START
08-06 15:09:01.738 3006-3413/? D/ActivityManager: bindService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms, action: com.google.android.gms.udc.service.START
08-06 15:09:01.758 3006-3585/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
caller:android.app.ApplicationThreadProxy#10932be9, r.packageName
:com.google.android.gms
08-06 15:09:01.768 3006-3586/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
caller:android.app.ApplicationThreadProxy#24164f9c, r.packageName
:com.google.android.gms
08-06 15:09:01.778 3006-3449/? D/ConnectivityService: returning
getActiveNetworkInfo :[type: WIFI[] - WIFI, state: CONNECTED/CONNECTED,
reason: (unspecified), extra: "KECOA SALTO", roaming: false, failover: false,
isAvailable: true, isConnectedToProvisioningNetwork: false]
08-06 15:09:01.788 27618-27719/? I/System.out:
KnoxVpnUidStorageknoxVpnSupported API value returned is false
08-06 15:09:01.788 3006-3373/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
08-06 15:09:01.793 3006-3373/? D/ActivityManager:
caller:android.app.ApplicationThreadProxy#18699da5, r.packageName
:com.google.android.gms
08-06 15:09:01.798 3006-3590/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
caller:android.app.ApplicationThreadProxy#259e957a, r.packageName
:com.google.android.gms
08-06 15:09:01.808 3006-4578/? D/ActivityManager: startService
callerProcessName:com.google.android.gms, calleePkgName:
com.google.android.gms
08-06 15:09:01.813 3006-4578/? D/ActivityManager:
caller:android.app.ApplicationThreadProxy#2c6d012b, r.packageName
:com.google.android.gms
08-06 15:09:01.918 4024-27128/? I/qtaguid: Untagging socket 87
08-06 15:09:02.128 3006-3032/? W/ActivityManager: Activity pause timeout for
ActivityRecord{1df5a9bd u0
com.launcher.rsupsanglah.personalNotif
/com.launcher.rsupsanglah.personal.MainActivity t392 f}
mDVFSHelper.acquire()
08-06 15:09:02.138 3006-3032/? V/WindowOrientationListener:
mSContextAutoRotationListener.getProposedRotation, mbResultFaceDectection:
false mSContextAutoRotationListener.getProposedRotation, Rotation: -1
08-06 15:09:02.138 3006-3032/? V/WindowManager:
rotationForOrientationLw(orient=-1, last=0); user=0 USER_ROTATION_LOCKED
sensorRotation=-1 mLidState=-1 mDockMode=0 mHdmiPlugged=false
08-06 15:09:02.143 3006-3032/? V/WindowOrientationListener:
mSContextAutoRotationListener.getProposedRotation, mbResultFaceDectection:
false mSContextAutoRotationListener.getProposedRotation, Rotation: -1
08-06 15:09:02.148 2352-2352/? I/SurfaceFlinger: id=973 createSurf
(1080x1920),1
flag=404, TubSettings
08-06 15:09:02.243 18041-18041/? E/AccessibilityManager: assistantMenuUpdate
invoking from manager:
08-06 15:09:02.323 3006-3043/? D/ActivityManager: bindService
callerProcessName:android, calleePkgName: com.android.defcontainer, action:
null
08-06 15:09:02.333 2360-2360/? E/installd: system dir 0 : /system/app/
08-06 15:09:02.338 3006-3449/? D/UsbSettingsManager: hasDefaults:
com.launcher.rsupsanglah.personalNotif FALSE
08-06 15:09:02.378 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.378 2360-2360/? E/installd: system dir 0 : /system/app/
08-06 15:09:02.388 18041-18041/? W/ResourceType: Failure getting entry for
0x7f020000 (t=1 e=0) (error -75)
08-06 15:09:02.388 18041-18041/? W/PackageManager: Failure retrieving
resources
for com.sec.android.provider.badge: Resource ID #0x7f020000
08-06 15:09:02.403 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.403 3006-4578/? D/SecContentProvider2: uri = 1 selection =
getApplicationUninstallationEnabled
mCursor = null
08-06 15:09:02.403 3006-4578/? D/ApplicationPolicy:
getApplicationUninstallationEnabled
getApplicationUninstallationEnabled : enabled true
08-06 15:09:02.403 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
08-06 15:09:02.408 3006-3373/? D/ActivityManager: post active user change for
0 fullscreen true record.isFloatingActivity() false
08-06 15:09:02.408 3006-3373/? D/KnoxTimeoutHandler: postActiveUserChange for
user 0
08-06 15:09:02.413 3006-3006/? D/PersonaManagerService: getPersonasForUser():
returning null!
08-06 15:09:02.408 3006-3373/? I/KnoxTimeoutHandler: postActiveUserChange,
showWhenLocked: false
08-06 15:09:02.413 3006-3006/? D/KnoxTimeoutHandler: handleActiveUserChange
for user 0
08-06 15:09:02.428 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.428 2360-2360/? E/installd: system dir 0 : /system/app/
08-06 15:09:02.448 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.448 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
08-06 15:09:02.468 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.468 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
08-06 15:09:02.488 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.488 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
system dir 2 : /vendor/app/
system dir 3 : /oem/app/
08-06 15:09:02.513 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.513 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
system dir 2 : /vendor/app/
system dir 3 : /oem/app/
08-06 15:09:02.518 18041-18041/? I/Timeline: Timeline: Activity_idle id:
android.os.BinderProxy#8c69e1e time:24624275
08-06 15:09:02.548 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.548 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
system dir 2 : /vendor/app/
system dir 3 : /oem/app/
08-06 15:09:02.593 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.593 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
system dir 2 : /vendor/app/
system dir 3 : /oem/app/
08-06 15:09:02.613 3006-3043/? D/PackageManager: remove MCS_UNBIND message
and Posting MCS_UNBIND 10 secs later
08-06 15:09:02.613 2360-2360/? E/installd: system dir 0 : /system/app/
system dir 1 : /system/priv-app/
system dir 2 : /vendor/app/
system dir 3 : /oem/app/
any idea? I'm new to android and sometimes the app runs okay (after multiple error like this), but when I clear the data/uninstalled, mostly resulting to this E/installd: system dir 0 : /system/app/ and sometimes E/FirebaseInstanceId: Token retrieval failed: SERVICE_NOT_AVAILABLE because I'm using firebase when generating new token. I already set generate the token only if device is connected to internet.
static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
jint bufID, jint priority, jstring tagObj, jstring msgObj)
{
const char* tag = NULL;
const char* msg = NULL;
if (msgObj == NULL) {
jniThrowNullPointerException(env, "println needs a message");
return -1;
}
// Rest of the method
}
As per the native print method for printing the message in Android, your message object should be non null value.
In your case, response object is null. so add null check before printing message
if(null != response)
{
Log.d("responsejson", response);
}
If you want to still print what is the value of response object even though it is null. Try to use below line.
Log.d("responsejson", "Response is "+response);
I am trying to register a new phoneAccount but I keep receiving the following error:
04-13 01:06:11.329 1267 2435 W Telecom : com.android.server.telecom.PhoneAccountRegistrar: phoneAccount ComponentInfo{com.my.otherApp/com.my.app.RNCallConnectionService} not found: TSI.rPA#Agc
04-13 01:06:11.329 1267 2435 W Telecom : com.android.server.telecom.PhoneAccountRegistrar: Phone account ComponentInfo{com.my.otherApp/com.my.app.RNCallConnectionService}, [a50dcea6cba1c8c30324624e9e54bfd19bb0b363], UserHandle{0} does not have BIND_TELECOM_CONNECTION_SE
RVICE permission.: TSI.rPA#Agc
04-13 01:06:11.330 1267 2435 E Telecom : com.android.server.telecom.TelecomServiceImpl$1: registerPhoneAccount [[ ] PhoneAccount: ComponentInfo{com.my.otherApp/com.my.app.RNCallConnectionService}, [a50dcea6cba1c8c30324624e9e54bfd19bb0b363], UserHandle{0} Capabilities: C
allProvider Schemes: tel Extras: null]: TSI.rPA#Agc
04-13 01:06:11.330 1267 2435 E Telecom : java.lang.SecurityException: PhoneAccount connection service requires BIND_TELECOM_CONNECTION_SERVICE permission.
04-13 01:06:11.330 1267 2435 E Telecom : at com.android.server.telecom.PhoneAccountRegistrar.registerPhoneAccount(PhoneAccountRegistrar.java:587)
04-13 01:06:11.330 1267 2435 E Telecom : at com.android.server.telecom.TelecomServiceImpl$1.registerPhoneAccount(TelecomServiceImpl.java:399)
04-13 01:06:11.330 1267 2435 E Telecom : at com.android.internal.telecom.ITelecomService$Stub.onTransact(ITelecomService.java:226)
04-13 01:06:11.330 1267 2435 E Telecom : at android.os.Binder.execTransact(Binder.java:573)
I have made sure to add <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"/> to my manifest.
Here is the relevant code
public class RNCallModule extends ReactContextBaseJavaModule {
static private String TAG = "RNCallModule +++++";
private ReactApplicationContext reactContext;
private String appName;
private TelecomManager tm;
private PhoneAccountHandle handle;
private PhoneAccount phoneAccount;
public RNCallModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
Boolean a = PackageManager.PERMISSION_GRANTED == this.reactContext.checkCallingOrSelfPermission(Manifest.permission.BIND_TELECOM_CONNECTION_SERVICE);
appName = getApplicationName(this.reactContext.getApplicationContext());
ComponentName cName = new ComponentName(this.reactContext.getApplicationContext(), RNCallConnectionService.class);
handle = new PhoneAccountHandle(cName, appName);
tm = (TelecomManager)this.reactContext.getApplicationContext().getSystemService(this.reactContext.getApplicationContext().TELECOM_SERVICE);
if(android.os.Build.VERSION.SDK_INT >= 26) {
phoneAccount = new PhoneAccount.Builder(handle, appName)
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
.build();
tm.registerPhoneAccount(phoneAccount);
}
phoneAccount = new PhoneAccount.Builder(handle, appName)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build();
tm.registerPhoneAccount(phoneAccount); // <<<<<< Here is where the error happens
}
// ...
}
Even though I had add the permission on my AndroidManifest.xml I still had to add this extra bit to it:
<service android:name="com.my.app.RNCallConnectionService"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
I'm working on a proof-of-concept app so that I can implement the feature in a larger app I'm making. I'm a bit new to Java and Android Dev but hopefully this shouldn't be too simple or complex of a question.
Basically, I'm trying to read in a list of strings from a CSV file and make it usable in displaying the list on the app's Main Activity.
I'm using an external class for reading in CSV's. Here's the class code:
CSVFile.java
package com.yourtechwhiz.listdisplay;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class CSVFile {
InputStream inputStream;
public CSVFile(InputStream inputStream){
this.inputStream = inputStream;
}
public List read(){
List resultList = new ArrayList();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
String csvLine;
while ((csvLine = reader.readLine()) != null) {
String[] row = csvLine.split(",");
resultList.add(row);
Log.d("VariableTag", row[0].toString());
}
}
catch (IOException ex) {
throw new RuntimeException("Error in reading CSV file: "+ex);
}
finally {
try {
inputStream.close();
}
catch (IOException e) {
throw new RuntimeException("Error while closing input stream: "+e);
}
}
return resultList;
}
}
Here's my main activity code:
MainActivity.java
package com.yourtechwhiz.listdisplay;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// Array of strings that's used to display on screen
String[] mobileArray = {"Android","IPhone","WindowsMobile","Blackberry",
"WebOS","Ubuntu","Windows7","Max OS X"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
prepArray();
//Display List on Activity
ArrayAdapter adapter = new ArrayAdapter<String>(this,
R.layout.activity_listview, mobileArray);
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);
}
//Get list of strings from CSV ready to use
private void prepArray() {
InputStream inputStream = getResources().openRawResource(R.raw.strings);
CSVFile csvFile = new CSVFile(inputStream);
List myList = csvFile.read();
//This is where it has an error
//Set first array in myList to this new array myArray
String[] myArray = myList.get(0);
}
}
I'm not actually to the point of setting the mobileArray array yet. Right now I'm just trying to "extract" the information out of the List object myList...
Can someone explain to me how this is done? Maybe I'm just not understanding the List type completely. It seems like when resultList is returned in the CSVFile read method, it's returned as an List object consisting of String array objects. But I can't seem to get it to work like that.
Any help is appreciated!
FINAL EDIT (working code)
private void prepArray() {
try{
CSVReader reader = new CSVReader(new InputStreamReader(getResources().openRawResource(R.raw.strings)));//Specify asset file name
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1] + "etc...");
Log.d("VariableTag", nextLine[0]);
}
}catch(Exception e){
e.printStackTrace();
Toast.makeText(this, "The specified file was not found", Toast.LENGTH_SHORT).show();
}
}
EDIT
Now my prepArray function looks like the following:
private void prepArray() {
try{
String csvfileString = this.getApplicationInfo().dataDir + File.separatorChar + "strings.csv"
File csvfile = new File(csvfileString);
CSVReader reader = new CSVReader(new FileReader("csvfile.getAbsolutePath()"));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1] + "etc...");
}
}catch(FileNotFoundException e){
e.printStackTrace();
Toast.makeText(this, "The specified file was not found", Toast.LENGTH_SHORT).show();
}
}
Still produces the FileNotFoundException.
EDIT 2/3
Here's the log that's produced when I run the app on an actual phone with the strings.csv in a subfolder of strings (src\main\assets\strings\strings.csv) with the change you requested to the code:
03/27 17:44:01: Launching app
$ adb push C:\Users\Roy\AndroidStudioProjects\ListDisplay\app\build\outputs\apk\app-debug.apk /data/local/tmp/com.yourtechwhiz.listdisplay
$ adb shell pm install -r "/data/local/tmp/com.yourtechwhiz.listdisplay"
pkg: /data/local/tmp/com.yourtechwhiz.listdisplay
Success
$ adb shell am start -n "com.yourtechwhiz.listdisplay/com.yourtechwhiz.listdisplay.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D
Connecting to com.yourtechwhiz.listdisplay
D/HyLog: I : /data/font/config/sfconfig.dat, No such file or directory (2)
D/HyLog: I : /data/font/config/dfactpre.dat, No such file or directory (2)
D/HyLog: I : /data/font/config/sfconfig.dat, No such file or directory (2)
W/ActivityThread: Application com.yourtechwhiz.listdisplay is waiting for the debugger on port 8100...
I/System.out: Sending WAIT chunk
I/dalvikvm: Debugger is active
I/System.out: Debugger has connected
I/System.out: waiting for debugger to settle...
Connected to the target VM, address: 'localhost:8609', transport: 'socket'
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: debugger has settled (1498)
I/dalvikvm: Could not find method android.view.Window$Callback.onProvideKeyboardShortcuts, referenced from method android.support.v7.view.WindowCallbackWrapper.onProvideKeyboardShortcuts
W/dalvikvm: VFY: unable to resolve interface method 16152: Landroid/view/Window$Callback;.onProvideKeyboardShortcuts (Ljava/util/List;Landroid/view/Menu;I)V
D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
W/dalvikvm: VFY: unable to find class referenced in signature (Landroid/view/SearchEvent;)
I/dalvikvm: Could not find method android.view.Window$Callback.onSearchRequested, referenced from method android.support.v7.view.WindowCallbackWrapper.onSearchRequested
W/dalvikvm: VFY: unable to resolve interface method 16154: Landroid/view/Window$Callback;.onSearchRequested (Landroid/view/SearchEvent;)Z
D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
I/dalvikvm: Could not find method android.view.Window$Callback.onWindowStartingActionMode, referenced from method android.support.v7.view.WindowCallbackWrapper.onWindowStartingActionMode
W/dalvikvm: VFY: unable to resolve interface method 16158: Landroid/view/Window$Callback;.onWindowStartingActionMode (Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
I/dalvikvm: Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.widget.TintTypedArray.getChangingConfigurations
W/dalvikvm: VFY: unable to resolve virtual method 455: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
I/dalvikvm: Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.widget.TintTypedArray.getType
W/dalvikvm: VFY: unable to resolve virtual method 477: Landroid/content/res/TypedArray;.getType (I)I
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0008
I/dalvikvm: Could not find method android.widget.FrameLayout.startActionModeForChild, referenced from method android.support.v7.widget.ActionBarContainer.startActionModeForChild
W/dalvikvm: VFY: unable to resolve virtual method 16589: Landroid/widget/FrameLayout;.startActionModeForChild (Landroid/view/View;Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
D/dalvikvm: VFY: replacing opcode 0x6f at 0x0002
I/dalvikvm: Could not find method android.content.Context.getColorStateList, referenced from method android.support.v7.content.res.AppCompatResources.getColorStateList
W/dalvikvm: VFY: unable to resolve virtual method 269: Landroid/content/Context;.getColorStateList (I)Landroid/content/res/ColorStateList;
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0006
I/dalvikvm: Could not find method android.content.res.Resources.getDrawable, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawable
W/dalvikvm: VFY: unable to resolve virtual method 418: Landroid/content/res/Resources;.getDrawable (ILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
I/dalvikvm: Could not find method android.content.res.Resources.getDrawableForDensity, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawableForDensity
W/dalvikvm: VFY: unable to resolve virtual method 420: Landroid/content/res/Resources;.getDrawableForDensity (IILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
W/dalvikvm: VFY: unable to resolve instanceof 140 (Landroid/graphics/drawable/RippleDrawable;) in Landroid/support/v7/widget/AppCompatImageHelper;
D/dalvikvm: VFY: replacing opcode 0x20 at 0x000c
W/System.err: java.io.FileNotFoundException: /csvfile.getAbsolutePath(): open failed: ENOENT (No such file or directory)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:462)
W/System.err: at java.io.FileInputStream.<init>(FileInputStream.java:78)
W/System.err: at java.io.FileInputStream.<init>(FileInputStream.java:105)
W/System.err: at java.io.FileReader.<init>(FileReader.java:66)
W/System.err: at com.yourtechwhiz.listdisplay.MainActivity.prepArray(MainActivity.java:43)
W/System.err: at com.yourtechwhiz.listdisplay.MainActivity.onCreate(MainActivity.java:26)
W/System.err: at android.app.Activity.performCreate(Activity.java:5287)
W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2145)
W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2231)
W/System.err: at android.app.ActivityThread.access$700(ActivityThread.java:139)
W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1401)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err: at android.os.Looper.loop(Looper.java:137)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5082)
W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err: at java.lang.reflect.Method.invoke(Method.java:515)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:598)
W/System.err: at dalvik.system.NativeStart.main(Native Method)
W/System.err: Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
W/System.err: at libcore.io.Posix.open(Native Method)
W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:446)
W/System.err: ... 19 more
I/Adreno-EGL: <qeglDrvAPI_eglInitialize:385>: EGL 1.4 QUALCOMM build: ()
OpenGL ES Shader Compiler Version: E031.24.00.01
Build Date: 12/27/13 Fri
Local Branch: qualcomm_only
Remote Branch:
Local Patches:
Reconstruct Branch:
D/OpenGLRenderer: Enabling debug mode 0
D/OpenGLRenderer: GL error from OpenGLRenderer: 0x502
E/OpenGLRenderer: GL_INVALID_OPERATION
Try OpenCSV - it will make your life easier.
First, add this package to your gradle dependencies as follows
implementation 'com.opencsv:opencsv:4.6'
Then you can either do
import com.opencsv.CSVReader;
import java.io.IOException;
import java.io.FileReader;
...
try {
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
String[] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1] + "etc...");
}
} catch (IOException e) {
}
or
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
List myEntries = reader.readAll();
Edit after comment
try {
File csvfile = new File(Environment.getExternalStorageDirectory() + "/csvfile.csv");
CSVReader reader = new CSVReader(new FileReader(csvfile.getAbsolutePath()));
String[] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1] + "etc...");
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "The specified file was not found", Toast.LENGTH_SHORT).show();
}
If you want to package the .csv file with the application and have it install on the internal storage when the app installs, create an assets folder in your project src/main folder (e.g., c:\myapp\app\src\main\assets\), and put the .csv file in there, then reference it like this in your activity:
String csvfileString = this.getApplicationInfo().dataDir + File.separatorChar + "csvfile.csv"
File csvfile = new File(csvfileString);
The following snippet reads a CSV file from the raw resources folder (which will be packed into your .apk file upon compilation).
Android by default does not create the raw folder. Create a raw folder under res/raw in your project and copy your CSV File into it. Keep the name of the CSV file lower case and convert it into text format when asked. My CSV file name is welldata.csv.
In the snippet, WellData is the model class (with constructor, getter and setter) and wellDataList is the ArrayList to store the data.
private void readData() {
InputStream is = getResources().openRawResource(R.raw.welldata);
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, Charset.forName("UTF-8")));
String line = "";
try {
while ((line = reader.readLine()) != null) {
// Split the line into different tokens (using the comma as a separator).
String[] tokens = line.split(",");
// Read the data and store it in the WellData POJO.
WellData wellData = new WellData();
wellData.setOwner(tokens[0]);
wellData.setApi(tokens[1]);
wellData.setLongitude(tokens[2]);
wellData.setLatitude(tokens[3]);
wellData.setProperty(tokens[4]);
wellData.setWellName(tokens[5]);
wellDataList.add(wellData);
Log.d("MainActivity" ,"Just Created " + wellData);
}
} catch (IOException e1) {
Log.e("MainActivity", "Error" + line, e1);
e1.printStackTrace();
}
}
This worked for me in Kotlin. You will need to place the myfile.csv file in the res/raw folder, creating the folder if it isn't there.
val inputStream: InputStream = resources.openRawResource(R.raw.myfile)
val reader = BufferedReader(InputStreamReader(inputStream, Charset.forName("UTF-8")))
reader.readLines().forEach {
//get a string array of all items in this line
val items = it.split(",")
//do what you want with each item
}
New coder for Android Studio. I've been researching how to read CSV files and this works best for my needs. (s0, s1, etc. Strings were defined at the beginning of my program).
File fileDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File fileToGet = new File(fileDirectory,"aFileName.csv");
try {
BufferedReader br = new BufferedReader(new FileReader(fileToGet));
String line;
while ((line = br.readLine()) !=null) {
String[] tokens = line.split(",");
s0=tokens[0].toString(); s1=tokens[1].toString(); s2=tokens[2].toString();
s3=tokens[3].toString(); s4=tokens[4].toString(); s5=tokens[5].toString();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Here is a simple way, which worked for me.
MainActivity.java
// Do not forget to call readWeatherData() in onCreate or wherever you need to :)
// Defining ordered collection as WeatherSample class
private List<WeatherSample> weatherSamples = new ArrayList<>();
private void readWeatherData() {
// Read the raw csv file
InputStream is = getResources().openRawResource(R.raw.data);
// Reads text from character-input stream, buffering characters for efficient reading
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, Charset.forName("UTF-8"))
);
// Initialization
String line = "";
// Initialization
try {
// Step over headers
reader.readLine();
// If buffer is not empty
while ((line = reader.readLine()) != null) {
Log.d("MyActivity","Line: " + line);
// use comma as separator columns of CSV
String[] tokens = line.split(",");
// Read the data
WeatherSample sample = new WeatherSample();
// Setters
sample.setMonth(tokens[0]);
sample.setRainfall(Double.parseDouble(tokens[1]));
sample.setSumHours(Integer.parseInt(tokens[2]));
// Adding object to a class
weatherSamples.add(sample);
// Log the object
Log.d("My Activity", "Just created: " + sample);
}
} catch (IOException e) {
// Logs error with priority level
Log.wtf("MyActivity", "Error reading data file on line" + line, e);
// Prints throwable details
e.printStackTrace();
}
}
WeatherSample.java
public class WeatherSample {
private String month;
private double rainfall;
private int sumHours;
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public double getRainfall() {
return rainfall;
}
public void setRainfall(double rainfall) {
this.rainfall = rainfall;
}
public int getSumHours() {
return sumHours;
}
public void setSumHours(int sumHours) {
this.sumHours = sumHours;
}
#Override
public String toString() {
return "WeatherSample{" +
"month='" + month + '\'' +
", rainfall=" + rainfall +
", sumHours=" + sumHours +
'}';
}
}
As for your source CSV file, first create directory:
app -> res (Right click) -> New -> Android resource directory -> Resource type (raw) -> OK
Then copy and paste your .csv file into that newly appeared directory:
raw (Right click) -> Show in Explorer
Here is the source file I used for the project:
data.csv
If you still have some error, here is a link to the full project:
Source Code
Hope it helps, have fun :)
With a file named filename.csv in the folder res/raw:
private void gettingItemsFromCSV() {
BufferedInputStream bufferedInputStream = new BufferedInputStream(getResources().openRawResource(R.raw.filename));
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(bufferedInputStream));
try {
String line;
while ((line = bufferedReader.readLine()) != null) {
Log.i("Test123", line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
In the latest Android 11 version, you need to do something like this:
val reader = CSVReader(
getApplication<Application>().applicationContext.assets.open("file-name.csv")
.reader()
)
val myEntries: List<Array<String>> = reader.readAll()
In build.gradle(app level):
dependencies {
...
// CSV reader
implementation 'com.opencsv:opencsv:4.6'
}
In AndroidManifest.xml:
<application
android:requestLegacyExternalStorage="true"
...
I am trying to do an XMPP Connection with Smack 4.1.0 rc1 from https://github.com/igniterealtime/Smack
I followed this guide: https://github.com/igniterealtime/Smack/wiki/Smack-4.1-Readme-and-Upgrade-Guide importing the Gradle.
Source code:
package com.example.xmpp_app;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import java.io.IOException;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the configuration for this new connection
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setUsernameAndPassword("test#example.com", "password123");
configBuilder.setResource("test");
configBuilder.setServiceName("example.com");
AbstractXMPPConnection connection = new XMPPTCPConnection(configBuilder.build());
// Connect to the server
try {
connection.connect();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
// Log into the server
try {
connection.login();
} catch (XMPPException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Disconnect from the server
connection.disconnect();
}
#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);
}
}
Gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
build gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.xmpp_app"
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile "org.igniterealtime.smack:smack-java7:4.1.0-rc1"
// Optional for XMPPTCPConnection
compile "org.igniterealtime.smack:smack-tcp:4.1.0-rc1"
// Optional for XMPP-IM (RFC 6121) support (Roster, Threaded Chats, …)
compile "org.igniterealtime.smack:smack-im:4.1.0-rc1"
// Optional for XMPP extensions support
compile "org.igniterealtime.smack:smack-extensions:4.1.0-rc1"
}
ERROR:
03-20 20:34:33.830 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method android.view.ViewGroup.onNestedScrollAccepted, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onNestedScrollAccepted
03-20 20:34:33.830 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve virtual method 11345: Landroid/view/ViewGroup;.onNestedScrollAccepted (Landroid/view/View;Landroid/view/View;I)V
03-20 20:34:33.850 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000
03-20 20:34:33.850 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method android.view.ViewGroup.onStopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onStopNestedScroll
03-20 20:34:33.850 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve virtual method 11351: Landroid/view/ViewGroup;.onStopNestedScroll (Landroid/view/View;)V
03-20 20:34:33.850 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000
03-20 20:34:33.920 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method android.support.v7.internal.widget.ActionBarOverlayLayout.stopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.setHideOnContentScrollEnabled
03-20 20:34:33.920 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve virtual method 9039: Landroid/support/v7/internal/widget/ActionBarOverlayLayout;.stopNestedScroll ()V
03-20 20:34:33.950 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000e
03-20 20:34:34.100 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations
03-20 20:34:34.110 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve virtual method 364: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
03-20 20:34:34.110 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
03-20 20:34:34.150 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType
03-20 20:34:34.150 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve virtual method 386: Landroid/content/res/TypedArray;.getType (I)I
03-20 20:34:34.150 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
03-20 20:34:35.790 1005-1005/com.example.xmpp_app D/dalvikvm﹕ GC_FOR_ALLOC freed 221K, 9% free 3164K/3452K, paused 105ms, total 115ms
03-20 20:34:38.420 1005-1005/com.example.xmpp_app D/dalvikvm﹕ GC_FOR_ALLOC freed 295K, 10% free 3382K/3744K, paused 90ms, total 93ms
03-20 20:34:40.250 1005-1005/com.example.xmpp_app D/dalvikvm﹕ GC_FOR_ALLOC freed 349K, 11% free 3531K/3952K, paused 80ms, total 85ms
03-20 20:34:40.310 1005-1005/com.example.xmpp_app E/dalvikvm﹕ Could not find class 'javax.naming.directory.InitialDirContext', referenced from method org.jivesoftware.smack.util.dns.javax.JavaxResolver.<clinit>
03-20 20:34:40.310 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve new-instance 1688 (Ljavax/naming/directory/InitialDirContext;) in Lorg/jivesoftware/smack/util/dns/javax/JavaxResolver;
03-20 20:34:40.320 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x22 at 0x000c
03-20 20:34:40.360 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method javax.naming.directory.DirContext.getAttributes, referenced from method org.jivesoftware.smack.util.dns.javax.JavaxResolver.lookupSRVRecords
03-20 20:34:40.360 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve interface method 12701: Ljavax/naming/directory/DirContext;.getAttributes (Ljava/lang/String;[Ljava/lang/String;)Ljavax/naming/directory/Attributes;
03-20 20:34:40.370 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x72 at 0x0011
03-20 20:34:40.370 1005-1005/com.example.xmpp_app D/dalvikvm﹕ DexOpt: unable to opt direct call 0x319e at 0x0e in Lorg/jivesoftware/smack/util/dns/javax/JavaxResolver;.<clinit>
03-20 20:34:40.410 1005-1005/com.example.xmpp_app W/dalvikvm﹕ Exception Ljava/lang/NoClassDefFoundError; thrown while initializing Lorg/jivesoftware/smack/util/dns/javax/JavaxResolver;
03-20 20:34:41.330 1005-1005/com.example.xmpp_app I/dalvikvm﹕ Could not find method javax.security.sasl.Sasl.createSaslClient, referenced from method org.jivesoftware.smack.sasl.javax.SASLJavaXMechanism.authenticateInternal
03-20 20:34:41.330 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve static method 12731: Ljavax/security/sasl/Sasl;.createSaslClient ([Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljavax/security/auth/callback/CallbackHandler;)Ljavax/security/sasl/SaslClient;
03-20 20:34:41.340 1005-1005/com.example.xmpp_app D/dalvikvm﹕ VFY: replacing opcode 0x77 at 0x001a
03-20 20:34:41.340 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to resolve exception class 1708 (Ljavax/security/sasl/SaslException;)
03-20 20:34:41.350 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: unable to find exception handler at addr 0x21
03-20 20:34:41.350 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: rejected Lorg/jivesoftware/smack/sasl/javax/SASLJavaXMechanism;.authenticateInternal ()V
03-20 20:34:41.350 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: rejecting opcode 0x0d at 0x0021
03-20 20:34:41.350 1005-1005/com.example.xmpp_app W/dalvikvm﹕ VFY: rejected Lorg/jivesoftware/smack/sasl/javax/SASLJavaXMechanism;.authenticateInternal ()V
03-20 20:34:41.350 1005-1005/com.example.xmpp_app W/dalvikvm﹕ Verifier rejected class Lorg/jivesoftware/smack/sasl/javax/SASLJavaXMechanism;
03-20 20:34:41.370 1005-1005/com.example.xmpp_app W/dalvikvm﹕ Exception Ljava/lang/VerifyError; thrown while initializing Lorg/jivesoftware/smack/SmackInitialization;
03-20 20:34:41.370 1005-1005/com.example.xmpp_app W/dalvikvm﹕ Exception Ljava/lang/VerifyError; thrown while initializing Lorg/jivesoftware/smack/ConnectionConfiguration;
03-20 20:34:41.380 1005-1005/com.example.xmpp_app D/AndroidRuntime﹕ Shutting down VM
03-20 20:34:41.380 1005-1005/com.example.xmpp_app W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb1a3bba8)
03-20 20:34:41.540 1005-1005/com.example.xmpp_app D/dalvikvm﹕ GC_FOR_ALLOC freed 438K, 14% free 3576K/4112K, paused 59ms, total 64ms
03-20 20:34:41.580 1005-1005/com.example.xmpp_app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.xmpp_app, PID: 1005
java.lang.VerifyError: org/jivesoftware/smack/sasl/javax/SASLJavaXMechanism
at org.jivesoftware.smack.sasl.javax.SASLJavaXSmackInitializer.initialize(SASLJavaXSmackInitializer.java:28)
at org.jivesoftware.smack.SmackInitialization.loadSmackClass(SmackInitialization.java:232)
at org.jivesoftware.smack.SmackInitialization.parseClassesToLoad(SmackInitialization.java:193)
at org.jivesoftware.smack.SmackInitialization.processConfigFile(SmackInitialization.java:163)
at org.jivesoftware.smack.SmackInitialization.processConfigFile(SmackInitialization.java:148)
at org.jivesoftware.smack.SmackInitialization.<clinit>(SmackInitialization.java:116)
at org.jivesoftware.smack.SmackConfiguration.getVersion(SmackConfiguration.java:96)
at org.jivesoftware.smack.ConnectionConfiguration.<clinit>(ConnectionConfiguration.java:38)
at com.example.xmpp_app.MainActivity.onCreate(MainActivity.java:29)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
03-20 20:39:44.485 1005-1005/com.example.xmpp_app I/Process﹕ Sending signal. PID: 1005 SIG: 9
Could someone help me with this problem, please? I am just trying to check if the connection works..
Replace smack-java7 with smack-android in your build.gradle. This is documented in Smack's README.
This is an upgrade of my last FCM XMPP Connection Server application. Now, this project uses the latest version at this time of the Smack library (4.1.8). I think that the library for android is pretty the same for the java server.
https://github.com/carlosCharz/fcmxmppserverv2
This is my sample java project to showcase the Firebase Cloud Messaging (FCM) XMPP Connection Server. This server sends data to a client app via the FCM CCS Server using the XMPP protocol.
https://github.com/carlosCharz/fcmxmppserver
And also I've created a video in youtube where I explain what the changes are.
https://www.youtube.com/watch?v=KVKEj6PeLTc
Hope you find it useful.
Here is a code snippet for the implementation:
public class CcsClient implements StanzaListener {
//Other code
public void connect() throws XMPPException, SmackException, IOException {
XMPPTCPConnection.setUseStreamManagementResumptionDefault(true);
XMPPTCPConnection.setUseStreamManagementDefault(true);
XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
config.setServiceName("FCM XMPP Client Connection Server");
config.setHost(Util.FCM_SERVER);
config.setPort(Util.FCM_PORT);
config.setSecurityMode(SecurityMode.ifpossible);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());
// Launch a window with info about packets sent and received
config.setDebuggerEnabled(mDebuggable);
// Create the connection
connection = new XMPPTCPConnection(config.build());
// Connect
connection.connect();
// Enable automatic reconnection
ReconnectionManager.getInstanceFor(connection).enableAutomaticReconnection();
// Handle reconnection and connection errors
connection.addConnectionListener(new ConnectionListener() {
#Override
public void reconnectionSuccessful() {
logger.log(Level.INFO, "Reconnection successful ...");
// TODO: handle the reconnecting successful
}
#Override
public void reconnectionFailed(Exception e) {
logger.log(Level.INFO, "Reconnection failed: ",
e.getMessage());
// TODO: handle the reconnection failed
}
#Override
public void reconnectingIn(int seconds) {
logger.log(Level.INFO, "Reconnecting in %d secs", seconds);
// TODO: handle the reconnecting in
}
#Override
public void connectionClosedOnError(Exception e) {
logger.log(Level.INFO, "Connection closed on error");
// TODO: handle the connection closed on error
}
#Override
public void connectionClosed() {
logger.log(Level.INFO, "Connection closed");
// TODO: handle the connection closed
}
#Override
public void authenticated(XMPPConnection arg0, boolean arg1) {
logger.log(Level.INFO, "User authenticated");
// TODO: handle the authentication
}
#Override
public void connected(XMPPConnection arg0) {
logger.log(Level.INFO, "Connection established");
// TODO: handle the connection
}
});
// Handle incoming packets (the class implements the StanzaListener)
connection.addAsyncStanzaListener(this,
stanza -> stanza.hasExtension(Util.FCM_ELEMENT_NAME, Util.FCM_NAMESPACE));
// Log all outgoing packets
connection.addPacketInterceptor(stanza -> logger.log(Level.INFO,
"Sent: {}", stanza.toXML()), stanza -> true);
connection.login(fcmServerUsername, mApiKey);
logger.log(Level.INFO, "Logged in: " + fcmServerUsername);
}
}
Try to connect server with XMPPConnection class.
How to connect:
XMPPConnection con = new XMPPTCPConnection("igniterealtime.org");
con.connect();