React Native: Override Error on Package without Duplicate - java

I'm trying to use the react-native-camera package but when I added this to my project, I wasn't able to see the camera, instead it was loading and a warning. Then I search on the internet for this warning and saw that I had to link this library manually and so I did. But when I try to build I got this:
Here is my MainApplication.java
import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.reactnative.camera.RNCameraPackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
#Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
public boolean canOverrideExistingModule() {
return true;
}
#Override
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new RNCameraPackage());
return packages;
}
#Override
protected String getJSMainModuleName() {
return "index";
}
};
#Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
#Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
}
/**
* Loads Flipper in React Native templates.
*
* #param context
*/
private static void initializeFlipper(Context context) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Android Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Getting this when trying to access the camera:
Possible Unhandled Promise Rejection (id: 0):
TypeError: CameraManager.checkVideoAuthorizationStatus is not a function
TypeError: CameraManager.checkVideoAuthorizationStatus is not a function
at requestPermissions$ (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:129653:61)
at tryCatch (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25682:19)
at Generator.invoke [as _invoke] (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25857:24)
at Generator.prototype.<computed> [as next] (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25725:23)
at tryCatch (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25682:19)
at invoke (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25758:22)
at http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25788:13
at tryCallTwo (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27046:7)
at doResolve (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27210:15)
at new Promise (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27069:5)

Well, the message sais it pretty clear in my opinion. Rect-Native 0.60+ uses autlinking to link native packages, so you are not require to use react-native link react-native-camera anymore.
Which means you don't need to import and have packages.add(new RNCameraPackage()); in your MainApplication.java
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new RNCameraPackage()); // Remove this line and the import statement
return packages;
}
You also need to remove all the other things that were added when running the react-native link command. Reinstall and your app should open now.
LE:
As backup, you can turn off autolinking for specific packages like below. Edit or create react-native.config.js add have the following.
module.exports = {
dependencies: {
'react-native-camera': {
platforms: {
android: null, // disable Android platform, other platforms will still autolink if provided
},
},
},
};

Related

Android Plugin not working in unity with class not found exception?

I tried creating a plugin but not working in unity.I do not have much idea about Android studio but watched this video to create an android plugin.I created a new android project without any activity.So I have written two classes UnityBinder.java and Gallery.java.They are given below
UnityBinder.java
package com.techripples.unityplugin;
import android.app.Activity;
import android.content.Intent;
public class UnityBinder {
public static void OpenGallery(Activity activity)
{
Intent intent =new Intent(activity,Gallery.class);
activity.startActivity(intent);
}
}
Gallery.java class given below
package com.techripples.unityplugin;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.MediaStore;
import android.net.Uri;
import android.database.*;
import com.unity3d.player.*;
public class Gallery extends Activity {
int PHOTO_GALLERY=1;
#Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Intent intent=new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent,PHOTO_GALLERY);
}
//it will run when user picks a photo from the gallery
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK && requestCode==PHOTO_GALLERY && data!=null)
{
Uri uri=data.getData();
String[] fileColoumn={MediaStore.Images.Media.DATA};
Cursor cursor=getContentResolver().query(uri,fileColoumn,null,null,null);
cursor.moveToFirst();
int coloumnIndex=cursor.getColumnIndex(fileColoumn[0]);
String photoPath=cursor.getString(coloumnIndex);
//Send path to unity to get photo
//GamObject Name,method name,argument
UnityPlayer.UnitySendMessage("Gallery","OnPhotoPick",photoPath);
Gallery.this.finish();//close activity
}
}
}
Next I have build and copied the jar file into Unity.The c# code written is as follows
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShowPicture : MonoBehaviour
{
Texture2D galleryImage;
bool isGalleryImageLoaded = false;
WWW www;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnGUI()
{
if(isGalleryImageLoaded)
{
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), galleryImage);
}
if(GUI.Button(new Rect(50,50,100,100),"Open"))
{
isGalleryImageLoaded = false;
AndroidJavaClass ajc = new AndroidJavaClass("com.unity.player.UnityPlayer");
//While asking question used AndroidJavaClass instead of AndroidJavaObject
AndroidJavaObject ajo = new AndroidJavaObject("com.techripples.unityplugin.UnityBinder");
ajo.CallStatic("OpenGallery", ajc.GetStatic<AndroidJavaObject>("currentActivity"));
}
if(www!=null && www.isDone)
{
galleryImage = new Texture2D(www.texture.width, www.texture.height);
galleryImage.SetPixels32(www.texture.GetPixels32());
galleryImage.Apply();
www = null;
isGalleryImageLoaded = true;
}
}
public void OnPhotoPick(string filePath)
{
Debug.Log(filePath);
www = new WWW("file://" + filePath);
}
}
The manifest file which I copied into the Unity folder.Assets>Plugins>Android. is as follows.
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="preferExternal">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application
android:theme="#style/UnityThemeSelector"
android:icon="#mipmap/app_icon"
android:label="#string/app_name">
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<activity android:name="com.techripples.unityplugin.Gallery"></activity>
</application>
The error I got from terminal is as follows
01-28 13:25:06.305 27032 27061 E Unity : java.lang.ClassNotFoundException: Didn't find class "com/unity/player/UnityPlayer" on path: DexPathList[[zip file "/data/app/com.testing.androidplugin-Aq1j3vpTxsomWMvd4kK7NQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.testing.androidplugin-Aq1j3vpTxsomWMvd4kK7NQ==/lib/arm, /data/app/com.testing.androidplugin-Aq1j3vpTxsomWMvd4kK7NQ==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib]]
Video of plugin done.What I am doing wrong here.
Making Of Android plugin
I dont know how the calls are being made or what should I write in the manifest for the activity to run.
If you open UnityPlayerActivity, you can see, that its package name is "com.unity3d.player" and class name is "UnityPlayer"
So you should change you unity player class name in C# script to "com.unity3d.player.UnityPlayer".
Another solution is add to your android plugin Unity classes and extend your activity from UnityPlayerActivity and you can call your methods directly from your plugin

Am I missing something to get google maps to open from android webview

Iam new to the android programming environment and am creating my first app. I am trying to get webview to open google maps when a google maps link is clicked within webview. Am I missing something as to why this is still opening the link in webview and not executing google maps instead? And when it is opening in webview it shows the destination fine but it does not show my location and states it is unable to determine my location on the bottom of the page being displayed
Here is the MainActivity
package com.example.micha.myapplication;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
/**
* WebViewClient subclass loads all hyperlinks in the existing WebView
*/
public class GeoWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// When user clicks a hyperlink, load in the existing WebView
view.loadUrl(url);
return true;
}
}
/**
* WebChromeClient subclass handles UI-related calls
* Note: think chrome as in decoration, not the Chrome browser
*/
public class GeoWebChromeClient extends WebChromeClient {
#Override
public void onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback) {
// Always grant permission since the app itself requires location
// permission and the user has therefore already granted it
callback.invoke(origin, true, false);
}
}
private WebView myWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myWebView = findViewById(R.id.webView);
WebView myWebView = findViewById(R.id.webView);
WebSettings webSettings = myWebView.getSettings();
myWebView.setWebViewClient(new GeoWebViewClient());
webSettings.setJavaScriptEnabled(true);
myWebView.getSettings().setGeolocationEnabled(true);
CookieManager.getInstance().setAcceptCookie(true);
//webSettings.setDomStorageEnabled(true);
myWebView.clearHistory();
myWebView.clearFormData();
myWebView.clearCache(true);
myWebView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if( url.startsWith("http:") || url.startsWith("https:") ) {
return false;
}
if(url.contains("https://www.google.com/maps/"))
{
Uri gmmIntentUri = Uri.parse(url);
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
if (mapIntent.resolveActivity(getPackageManager()) != null) {
startActivity(mapIntent);
}
return true;
}
// Otherwise allow the OS to handle things like tel, mailto, etc.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent );
return true;
}
});
myWebView.loadUrl("http://www.example.com");
//THIS IS TO DOWNLOAD THE PDF FILES OR OTHER DOWNLOAD LINKS
myWebView.setDownloadListener(new DownloadListener() {
#Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
});
}
#Override
public void onBackPressed() {
if (myWebView.canGoBack()) {
myWebView.goBack();
return;
}
super.onBackPressed();
}
}
Here is the AndroidManifest.XML
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.micha.myapplication">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACTION_DIAL"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_principal"
android:label="Admin Tools"
android:supportsRtl="true"
android:theme="#style/Theme.AppCompat.NoActionBar">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Found the problem.
if( url.startsWith("http:") || url.startsWith("https:") ) {
was preventing google maps from opening as it was forcing any url with https to stay within the webview. modified it to
if( url.startsWith("http:")) {
and all is good now.

Android Unable to instantiate activity: Didn't find class on path

I've imported project into eclipse and when I try to run it, then this exception is thrown:
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.polygraf/com.polygraf.activity.Dashboard}: java.lang.ClassNotFoundException: Didn't find class "com.polygraf.activity.Dashboard" on path: /data/app/com.polygraf-1.apk
I've tried to clean the project, then check if all class names and manifest are ok, but still can't find why this happens. Can you help me a little please?
Dashbard class:
public class Dashboard extends FragmentActivity {
private static final String WELCOME_TYPE = "WELCOME_TYPE";
private static final String HELP_TYPE = "HELP_TYPE";
public static final String ADRESS_CONTENT = "ADRESS_CONTENT";
public static final String DOC_NAME = "DOC_NAME";
private Transcript mContent;
private ISettableContent mListOfDocument;
private String mAddress;
private String mDocName;
public Dashboard() {
}
/** Called with the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
boolean content = false;
// View gc = (NoSaveStateFrameLayout)
// findViewById(R.id.content_fragment);
//
Fragment frContent = getSupportFragmentManager().findFragmentById(R.id.content_fragment);
mContent = ((IGetContent) frContent).getContent();
TranscriptSetting cc = Polygraf.getInstance().getContentSetting();
Fragment frDocumentsList = getSupportFragmentManager().findFragmentById(R.id.documents);
mListOfDocument = (ISettableContent) frDocumentsList;
cc.registerContent(mListOfDocument);
if (getIntent().hasExtra(ADRESS_CONTENT)) {
mAddress = getIntent().getStringExtra(ADRESS_CONTENT);
mDocName = getIntent().getStringExtra(DOC_NAME);
mContent.setAddress(mAddress, mDocName);
content = true;
} else if (getIntent().hasExtra(WELCOME_TYPE)) {
content = true;
prepareVisibilityBtnTranscript();
} else if (getIntent().hasExtra(HELP_TYPE)) {
content = true;
mContent.showHelp();
}
if (content) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.hide(frDocumentsList);
ft.commit();
// because on diferent layouts for small and large device
// some views missing, so the test is inportant
View contentLayout = findViewById(R.id.contentLayout);
if (contentLayout != null) {
contentLayout.setVisibility(View.VISIBLE);
}
prepareVisibilityBtnWelcome();
// cp.setContent(mContent);
}
cc.registerContent(mContent);
// cp.setListener(cc);
}
.
.
.
}
And manifest file:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="17" />
<application
android:name=".Polygraf"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#drawable/icon"
android:label="#string/skeleton_app"
android:theme="#android:style/Theme.Black.NoTitleBar" >
<activity
android:name="com.polygraf.activity.Dashboard"
android:configChanges="orientation|keyboard" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- This places this activity into the main app list. -->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.polygraf.activity.SettingActivity"
android:label="#string/skeleton_app" />
<activity
android:name="com.polygraf.activity.ContentActivity"
android:label="#string/skeleton_app" >
</activity>
<activity
android:name="com.polygraf.activity.PlayVideo"
android:configChanges="orientation|keyboard"
android:label="#string/skeleton_app" />
</application>
I suppose you're using Eclipse. Your activity is there alright, but Eclipse didn't include the support package in the APK ... If you look above your error in stacktrace you will notice the root of your problem: "Unable to find FragmentActivity". Or you can unpack the apk, undex it and you will see the compatibility package classes were not included.
To fix this, right-click your project, properties, build path and go to export tab. There make sure "Android private libraries" are checked. A clean and rebuild should put you on track ...
After i spend a while on this problem, the solution that i found is a conflict between importing Properties > Android - appcompat_v7 and appcompat_v4 that was added in the libs folder. After i remove the appcompat_v4 the error no longer appear.
I hope that answer can help in the future someone.
You should import new appcompat_v7 from sdk and use it as a built path,it works for me.

getGSMSignalStrength() Always Returns 99

I know there is another question on here relating to this, but I don't think it applies to me, as I'm pretty sure I use GSM (isGSM() returns true). In any case, getCdmaDbm returns -1 for me anyway. I am using Android 4.1.1 and an HTC One X. Here is my code (most of which isn't mine):
MainActivity:
package com.example.receptionlookup;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.widget.Toast;
public class MainActivity extends Activity {
TelephonyManager Tel;
MyPhoneStateListener MyListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Update the listener, and start it */
MyListener = new MyPhoneStateListener();
Tel = ( TelephonyManager )getSystemService(Context.TELEPHONY_SERVICE);
Tel.listen(MyListener ,PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
/* Called when the application is minimized */
#Override
protected void onPause()
{
super.onPause();
Tel.listen(MyListener, PhoneStateListener.LISTEN_NONE);
}
/* Called when the application resumes */
#Override
protected void onResume()
{
super.onResume();
Tel.listen(MyListener,PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
/* —————————– */
/* Start the PhoneState listener */
/* —————————– */
private class MyPhoneStateListener extends PhoneStateListener
{
/* Get the Signal strength from the provider, each tiome there is an update */
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength)
{
super.onSignalStrengthsChanged(signalStrength);
Toast.makeText(getApplicationContext(), "Go to Firstdroid!!! GSM Cinr = "
+ String.valueOf(signalStrength.getGsmSignalStrength()), Toast.LENGTH_SHORT).show();
}
};/* End of private Class */
}
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.receptionlookup"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.receptionlookup.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
</manifest>
Does anyone know what the problem is? If I go to Settings->About->Network, I can see the signal strength there. Isn't there some way to just read this value? I've tried several third party apps, and none of them are able to read my signal strength either. I've also tried the proprietary getGSMSignalBar() method, but I get a NoSuchMethodException.
As you can read in the 3GPP 127 007 8.5 the implementation of the at+csq is optional (the command which suppose to give the signal strength). Apparently HTC hide this value from 3rd party applications and they probably have another way to achieve that value for display in their own proprietary Settings application.
The fact that other applications also cannot get that information justifies my case.
This issue is tightly related to yours - thay said that HTC is one of the OEMs that does not worth the modem related developing time.
Try this:
Class signalStrengthClass = signalStrength.getClass();
try {
Method method = signalStrengthClass.getMethod(
"getGsmSignalBar", null);
method.setAccessible(true);
Integer bars = (Integer) method.invoke(signalStrength,
(Object[]) null);
}
} catch (Exception e) {
e.printStackTrace();
}

Why read logcat in loop read only one time

I run my service (write logcat to file) on any emulators and real devices from 2.3.3 to 4.1. All OK.
On this devices generated right log:
--------- beginning of /dev/log/main
--------- beginning of /dev/log/system
I/ActivityManager( 3386): START {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher/com.androWAcivtMaae( 36:IvldakgNme W/ActivityManager( 3386): Duplcaefns eus orcitRod45c6 o.vnotsolet.tiiyilg
I/ActivityManager( 3386): Displayed com.android.calculator2/.Calculator: +9s374ms<br>
.....
.....
But when I run service on 4.1.2 (samsung (google) Nexus S (soju, crespo), SDK 16, flash 485486, build JZO54K) or 2.3.6, my service stoped after one line in logs.
On this devices generated wrong log:
--------- beginning of /dev/log/main
Only print one line and nothing.... Service stay in memory, but not work right...
This is my code
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.logcatt"
android:versionCode="1"
android:versionName="0.5">
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_LOGS" />
<application android:theme="#android:style/Theme.NoTitleBar">
<activity android:name=".ActivityMain" android:label="logcatt">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BroadcastBoot" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".ServiceMain" android:enabled="true" />
</application>
</manifest>
Activity
package com.my.logcatt;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class ActivityMain extends Activity
{
#Override
public void onCreate( Bundle savedInstanceState)
{
super.onCreate( savedInstanceState);
setContentView( R.layout.main);
try { startService( new Intent( getApplicationContext(), ServiceMain.class)); } catch( Exception e) {}
}
}
Service
package com.my.logcatt;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader;
import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
public class ServiceMain extends Service
{
public static Process procLogcatClean = null;
public static Process procLogcatAM = null;
public static BufferedReader readerLogcat = null;
public static void fLog( String sLogMessage)
{
FileWriter fileLog = null;
BufferedWriter bufferLog = null;
try
{
fileLog = new FileWriter( Environment.getExternalStorageDirectory().getAbsolutePath() + "/123.log", true);
if( fileLog != null)
{
bufferLog = new BufferedWriter( fileLog);
bufferLog.write( sLogMessage + "\r\n");
bufferLog.flush();
}
}
catch( Exception e) {}
finally
{
if( bufferLog != null) { try { bufferLog.close(); } catch( Exception e) {} }
if( fileLog != null) { try { fileLog.close(); } catch( Exception e) {} }
}
}
#Override
public void onCreate()
{
super.onCreate();
startService();
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
public void startService()
{
final Thread thread = new Thread()
{
public void run()
{
try
{
Runtime localRuntimeClear = Runtime.getRuntime();
String[] sLogcatClear = new String[ 2];
sLogcatClear[ 0] = "logcat";
sLogcatClear[ 1] = "-c";
procLogcatClean = localRuntimeClear.exec( sLogcatClear);
procLogcatClean.waitFor();
Runtime localRuntimeAM = Runtime.getRuntime();
String[] sLogcatAM = new String[ 2];
sLogcatAM[ 0] = "logcat";
sLogcatAM[ 1] = "ActivityManager:I *:S";
procLogcatAM = localRuntimeAM.exec( sLogcatAM);
readerLogcat = new BufferedReader( new InputStreamReader( procLogcatAM.getInputStream()), 1024);
String str = "";
while( true)
{
str = "";
try
{
if( readerLogcat != null)
{
str = readerLogcat.readLine();
fLog( str);
}
}
catch( Exception e) {}
if( str.compareTo( "") == 0) continue;
}
}
catch( Exception e) {}
finally {}
}
};
thread.setPriority( Thread.MAX_PRIORITY);
thread.start();
}
}
What is wrong?
On 4.1.2., Only rooted and system applications can access logcat. If rooted, you could use "su logcat".
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/6U4A5irWang
I suspect that you will find that this line throws an exception which you do not handle (bad practice btw - if you had a proper catch, you would have found this I think).
procLogcatAM = localRuntimeAM.exec( sLogcatAM);
Otherwise, check for the Android version and do something different or check for the permission refusal. Or, restrict your app to < 4.1.

Categories