I have updated the DJI SDK from 4.3.2 to 4.4.1 in the last days. I'm trying to get it to work but it somehow doesn't recognize when I attach the remote controller of the drone.
Hardware/Software used:
Smartphone: Google Pixel XL
Smartphone OS: Android 8.1.0
Drone: DJI Phantom 4 Pro
DJI SDK: 4.4.1
Please not that I NEED to make it work with API level >=26 because of other dependencies and I can't go lower than that.
build.gradle
apply plugin: 'com.android.application'
repositories {
maven { url 'https://maven.google.com' }
}
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.test.droneapp"
minSdkVersion 19
targetSdkVersion 26
versionCode 9
versionName "1.0"
//Enabling multidex support
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
useLibrary 'org.apache.http.legacy'
ndk {
abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a'
}
}
lintOptions {
disable 'MissingTranslation'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dexOptions {
preDexLibraries = false
javaMaxHeapSize "4g"
}
packagingOptions{
doNotStrip "*/*/libdjivideo.so"
doNotStrip "*/*/libSDKRelativeJNI.so"
doNotStrip "*/*/libFlyForbid.so"
doNotStrip "*/*/libduml_vision_bokeh.so"
doNotStrip "*/*/libyuv2.so"
doNotStrip "*/*/libGroudStation.so"
doNotStrip "*/*/libFRCorkscrew.so"
doNotStrip "*/*/libUpgradeVerify.so"
doNotStrip "*/*/libFR.so"
}
}
repositories {
flatDir {
dirs 'libs'
}
google()
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
// Support Library
compile "com.android.support:support-v4:26.1.0"
compile "com.android.support:recyclerview-v7:26.1.0"
compile "com.android.support:appcompat-v7:26.1.0"
compile "com.android.support:design:26.1.0"
// Google Play Services
compile "com.google.android.gms:play-services-maps:11.6.2"
compile "com.google.android.gms:play-services-auth:11.6.2"
compile "com.google.android.gms:play-services-gcm:11.6.2"
compile "com.google.android.gms:play-services-location:11.6.2"
// MultiDex
compile 'com.android.support:multidex:1.0.1'
// DJI SDK
// compile ('com.dji:dji-sdk:4.3.2')
compile 'com.dji:dji-sdk:4.4.1'
provided 'com.dji:dji-sdk-provided:4.4.1'
}
LauncherApplication.java
package com.test.droneapp;
import android.app.Application;
import android.content.Context;
import android.os.Environment;
import android.support.multidex.MultiDex;
import com.crashlytics.android.Crashlytics;
import com.secneo.sdk.Helper;
import java.io.File;
import io.fabric.sdk.android.Fabric;
public class LauncherApplication extends Application {
private DJIApplication mDJIApplication;
#Override
protected void attachBaseContext(Context paramContext) {
super.attachBaseContext(paramContext);
MultiDex.install(this);
Helper.install(this);
if (mDJIApplication == null) {
mDJIApplication = new DJIApplication();
mDJIApplication.setContext(this);
}
}
#Override
public void onCreate() {
super.onCreate();
mDJIApplication.onCreate();
// Initialize Fabric
Fabric.with(this, new Crashlytics());
}
}
DJIApplication.java
package com.test.droneapp;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import dji.common.error.DJIError;
import dji.common.error.DJISDKError;
import dji.sdk.base.BaseComponent;
import dji.sdk.base.BaseProduct;
import dji.sdk.camera.Camera;
import dji.sdk.products.Aircraft;
import dji.sdk.products.HandHeld;
import dji.sdk.sdkmanager.DJISDKManager;
public class DJIApplication extends Application {
private static final String TAG = "DroneApp";
public static final String FLAG_CONNECTION_CHANGE = "dji_sdk_connection_change";
private DJISDKManager.SDKManagerCallback mDJISDKManagerCallback;
private BaseProduct.BaseProductListener mDJIBaseProductListener;
private BaseComponent.ComponentListener mDJIComponentListener;
private static BaseProduct mProduct;
public Handler mHandler;
private Application instance;
public void setContext(Application application) {
instance = application;
}
#Override
public Context getApplicationContext() {
return instance;
}
public DJIApplication() {
}
public static synchronized BaseProduct getProductInstance() {
if (null == mProduct) {
mProduct = DJISDKManager.getInstance().getProduct();
}
return mProduct;
}
public static synchronized Aircraft getAircraftInstance() {
if (!isAircraftConnected()) return null;
return (Aircraft) getProductInstance();
}
public static synchronized Camera getCameraInstance() {
if (getProductInstance() == null) return null;
Camera camera = null;
if (getProductInstance() instanceof Aircraft) {
camera = ((Aircraft) getProductInstance()).getCamera();
} else if (getProductInstance() instanceof HandHeld) {
camera = ((HandHeld) getProductInstance()).getCamera();
}
return camera;
}
public static boolean isAircraftConnected() {
return getProductInstance() != null && getProductInstance() instanceof Aircraft;
}
public static boolean isProductModuleAvailable() {
return (null != DJIApplication.getProductInstance());
}
public static boolean isCameraModuleAvailable() {
return isProductModuleAvailable() &&
(null != DJIApplication.getProductInstance().getCamera());
}
public static boolean isPlaybackAvailable() {
return isCameraModuleAvailable() &&
(null != DJIApplication.getProductInstance().getCamera().getPlaybackManager());
}
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(Looper.getMainLooper());
mDJIComponentListener = new BaseComponent.ComponentListener() {
#Override
public void onConnectivityChange(boolean isConnected) {
notifyStatusChange();
}
};
mDJIBaseProductListener = new BaseProduct.BaseProductListener() {
#Override
public void onComponentChange(BaseProduct.ComponentKey key, BaseComponent oldComponent, BaseComponent newComponent) {
if (newComponent != null) {
newComponent.setComponentListener(mDJIComponentListener);
}
notifyStatusChange();
}
#Override
public void onConnectivityChange(boolean isConnected) {
notifyStatusChange();
}
};
/**
* When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
* the SDK Registration result and the product changing.
*/
mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
//Listens to the SDK registration result
#Override
public void onRegister(DJIError error) {
if (error == DJISDKError.REGISTRATION_SUCCESS) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Register Success", Toast.LENGTH_LONG).show();
}
});
DJISDKManager.getInstance().startConnectionToProduct();
} else {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Register sdk fails, check network is available", Toast.LENGTH_LONG).show();
}
});
}
Log.e("TAG", error.toString());
}
//Listens to the connected product changing, including two parts, component changing or product connection changing.
#Override
public void onProductChange(BaseProduct oldProduct, BaseProduct newProduct) {
mProduct = newProduct;
if (mProduct != null) {
mProduct.setBaseProductListener(mDJIBaseProductListener);
}
notifyStatusChange();
}
};
//Check the permissions before registering the application for android system 6.0 above.
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (permissionCheck == 0 && permissionCheck2 == 0)) {
//This is used to start SDK services and initiate SDK.
DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);
Toast.makeText(getApplicationContext(), "registering, pls wait...", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Please check if the permission is granted.", Toast.LENGTH_LONG).show();
}
}
private void notifyStatusChange() {
mHandler.removeCallbacks(updateRunnable);
mHandler.postDelayed(updateRunnable, 500);
}
private Runnable updateRunnable = new Runnable() {
#Override
public void run() {
Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
getApplicationContext().sendBroadcast(intent);
}
};
}
ConnectionActivity.java (Just the important parts...)
package com.test.droneapp;
import android.Manifest;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.SimpleColorFilter;
import com.geniusforapp.fancydialog.FancyAlertDialog;
import com.securepreferences.SecurePreferences;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.test.droneapp.utils.NetworkUtils;
import com.test.droneapp.utils.SystemUtils;
import com.test.droneapp.utils.UIUtils;
import dji.common.error.DJIError;
import dji.common.error.DJISDKError;
import dji.log.DJILog;
import dji.sdk.base.BaseProduct;
import dji.sdk.sdkmanager.DJISDKManager;
public class ConnectionActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "droneapp";
private static final String[] REQUIRED_PERMISSION_LIST = new String[]{
Manifest.permission.VIBRATE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.WAKE_LOCK,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
};
private List<String> missingPermission = new ArrayList<>();
private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
private static final int REQUEST_PERMISSION_CODE = 12345;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
checkAndRequestPermissions();
setContentView(R.layout.activity_connection);
initUI();
// Register the broadcast receiver for receiving the device connection's changes.
IntentFilter filter = new IntentFilter();
filter.addAction(DJIApplication.FLAG_CONNECTION_CHANGE);
registerReceiver(mReceiver, filter);
}
#Override
public void onResume() {
Log.e(TAG, "onResume");
super.onResume();
}
#Override
public void onPause() {
Log.e(TAG, "onPause");
super.onPause();
}
#Override
public void onStop() {
Log.e(TAG, "onStop");
super.onStop();
}
#Override
protected void onDestroy() {
Log.e(TAG, "onDestroy");
unregisterReceiver(mReceiver);
super.onDestroy();
}`
/**
* Checks if there is any missing permissions, and
* requests runtime permission if needed.
*/
private void checkAndRequestPermissions() {
// Check for permissions
for (String eachPermission : REQUIRED_PERMISSION_LIST) {
if (ContextCompat.checkSelfPermission(this, eachPermission) != PackageManager.PERMISSION_GRANTED) {
missingPermission.add(eachPermission);
}
}
// Request for missing permissions
if (!missingPermission.isEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(this,
missingPermission.toArray(new String[missingPermission.size()]),
REQUEST_PERMISSION_CODE);
} else {
startSDKRegistration();
}
}
/**
* Result of runtime permission request
*/
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Check for granted permission and remove from missing list
if (requestCode == REQUEST_PERMISSION_CODE) {
for (int i = grantResults.length - 1; i >= 0; i--) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
missingPermission.remove(permissions[i]);
}
}
}
// If there is enough permission, we will start the registration
if (missingPermission.isEmpty()) {
startSDKRegistration();
} else {
UIUtils.errorSnacky("Missing permissions!!!");
}
}
protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
refreshSDKRelativeUI();
}
};
private void startSDKRegistration() {
if (isRegistrationInProgress.compareAndSet(false, true)) {
AsyncTask.execute(new Runnable() {
#Override
public void run() {
showToast( "registering, pls wait...");
DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
#Override
public void onRegister(DJIError djiError) {
if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
DJILog.e("App registration", DJISDKError.REGISTRATION_SUCCESS.getDescription());
DJISDKManager.getInstance().startConnectionToProduct();
runOnUiThread(new Runnable() {
#Override
public void run() {
UIUtils.successSnacky("Register Success");
}
});
} else {
runOnUiThread(new Runnable() {
#Override
public void run() {
UIUtils.errorSnacky( "Register sdk fails, check network is available");
}
});
}
Log.v(TAG, djiError.getDescription());
}
#Override
public void onProductChange(BaseProduct oldProduct, BaseProduct newProduct) {
Log.d(TAG, String.format("onProductChanged oldProduct:%s, newProduct:%s", oldProduct, newProduct));
}
});
}
});
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.test.droneapp">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature
android:name="android.hardware.usb.host"
android:required="false" />
<uses-feature
android:name="android.hardware.usb.accessory"
android:required="true" />
<application
android:name=".LauncherApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="android:icon">
<!-- DJI SDK -->
<uses-library android:name="com.android.future.usb.accessory" />
<meta-data
android:name="com.dji.sdk.API_KEY"
android:value="XXXXXXXXXXXXXXXXXXXXXX" />
<activity
android:name="dji.sdk.sdkmanager.DJIAoaControllerActivity"
android:theme="#android:style/Theme.Translucent" >
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
<service android:name="dji.sdk.sdkmanager.DJIGlobalService" >
</service>
<!-- DJI SDK -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".ConnectionActivity"
android:label="#string/app_name"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Everything worked fine on 4.3.2 and after the update I followed the guides on the DJI website to make it work but I can't figure out what I've done wrong.
Any help would be appreciated!
You can get RemoteController object by using below code on Application class
/**
* This method is used for getting RemoteController instance.
*
* #return
*/
public static synchronized RemoteController getRemoteControllerInstance() {
if (!isAircraftConnected()) return null;
return getAircraftInstance().getRemoteController();
}
Related
I ask for help, there is a class for setting live wallpapers on android. Everything seems to be connected and should work as it should, but nothing works. Tell me what's wrong?
onCreateEngine is not called for some reason at startActivity.
package com.atticpic;
import android.os.Environment;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.media.ThumbnailUtils;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.net.Uri;
import android.service.wallpaper.WallpaperService;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.app.PendingIntent;
import android.app.Activity;
public class ReactVideoWallpaperModule extends ReactContextBaseJavaModule {
Context context;
private File file;
private VideoWallpaper mVideoWallpaper;
public ReactVideoWallpaperModule(ReactApplicationContext reactContext) {
super(reactContext);
context = reactContext.getApplicationContext();
}
#Override
public String getName() {
return "ReactVideoWallpaper";
}
#ReactMethod
void setWallpaperVideo(final String videoUri) {
mVideoWallpaper = new VideoWallpaper();
file = new File(videoUri);
if (!file.exists()) {
Log.i( null, "File not found: " + file);
}
mVideoWallpaper.setToWallPaper(context, file.getAbsolutePath());
}
public class VideoWallpaper extends WallpaperService {
#Override
public Engine onCreateEngine() {
Log.i( TAG, "( START VideoEngine )");
return new VideoWallpagerEngine();
}
private final String TAG = VideoWallpaper.class.getName();
private String sVideoPath;
protected int playheadTime = 0;
public void setToWallPaper(Context context,String videoPath) {
try {
context.clearWallpaper();
} catch (IOException e) {
e.printStackTrace();
}
sVideoPath = videoPath;
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
//intent.setAction(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT);
//intent.setClass(context, VideoWallpaper.class);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(context, VideoWallpaper.class));
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
class VideoWallpagerEngine extends Engine {
private final String TAG = getClass().getSimpleName();
private MediaPlayer mediaPlayer;
public VideoWallpagerEngine() {
super();
Log.i( TAG, "( VideoEngine )");
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(sVideoPath);
mediaPlayer.setLooping(true);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
Log.i( TAG, "onSurfaceCreated" );
super.onCreate(surfaceHolder);
}
#Override
public void onDestroy() {
Log.i( TAG, "onSurfaceCreated" );
super.onDestroy();
}
#Override
public void onVisibilityChanged(boolean visible) {
Log.i( TAG, "onSurfaceCreated" );
if (visible){
mediaPlayer.start();
}else {
mediaPlayer.pause();
}
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
Log.i( TAG, "onSurfaceCreated" );
mediaPlayer.setSurface(holder.getSurface());
mediaPlayer.start();
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i( TAG, "onSurfaceCreated" );
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
Log.i( TAG, "( INativeWallpaperEngine ): onSurfaceDestroyed" );
playheadTime = mediaPlayer.getCurrentPosition();
mediaPlayer.reset();
mediaPlayer.release();
}
}
}
}
Call to react native
const DownloadImage = async (item) => { const result = await NativeModules.ReactVideoWallpaper.setWallpaperVideo(dirFile); }
There is a video file, there are no errors, tell me what is wrong?
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.atticpic.ReactVideoWallpaperModule.VideoWallpaper"
android:exported="true"
android:label="#string/app_name"
android:permission="android.permission.BIND_WALLPAPER"
android:process=":wallpaper">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/livewallpaper" />
</service>
</application>
It is expected to be completed and as a result of success, the installation of video wallpapers is expected.
I'm trying to load images from Camera and Gallery to load inside Tensor flow lite model.
When loading image from gallery, I'm getting following errors.
2021-01-02 11:48:03.309 9858-9858/com.example.coco_classif E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/Pictures/20200714_135735 (1).jpg: open failed: EACCES (Permission denied)
2021-01-02 11:48:03.332 9858-9858/com.example.coco_classif E/ErrorĀ log: java.lang.NullPointerException: Cannot load null bitmap.
NOTE: Issues seems coming from the try catch block, loading from camera works fine
mainfest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.coco_classif">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Coco_classif">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Main Activity
package com.example.coco_classif;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Image;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MainActivity extends AppCompatActivity {
private static final int CAMERA_PERMISSION_REQUEST_CODE = 1000;
private static final int CAMERA_REQUEST_CODE = 10001;
private ImageView imageView;
private ListView listView;
private ImageClassifier imageClassifier;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inaializeUIElements();
}
private void inaializeUIElements() {
imageView = findViewById(R.id.iv_capture);
listView = findViewById(R.id.lv_probabilities);
Button takepicture = findViewById(R.id.bt_take_picture);
try {
imageClassifier = new ImageClassifier(this);
} catch (IOException e) {
Log.e("Error While Creating Image Classifier", "Error" +e);
}
takepicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(hasPermission()) {
selectImage();
}else{
requestPermission();
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
Bitmap photo = (Bitmap) Objects.requireNonNull(Objects.requireNonNull(data).getExtras()).get("data");
imageView.setImageBitmap(photo);
List<ImageClassifier.Recognition> predictions = imageClassifier.recognizeImage(photo, 0);
final List<String> predictionList = new ArrayList<>();
for(ImageClassifier.Recognition recog: predictions){
predictionList.add("Label: " + recog.getName() + "Confidence: " + recog.getConfidance());
}
ArrayAdapter<String> predictionsAdapter = new ArrayAdapter<>(
this,R.layout.support_simple_spinner_dropdown_item,predictionList);
listView.setAdapter(predictionsAdapter);
}
else if (requestCode == 2) {
try {
Uri selectedImage = data.getData();
String[] filePath = new String[]{MediaStore.Images.Media.DATA};
Cursor c = getContentResolver().query(selectedImage,filePath, null, null, null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePath[0]);
String picturePath = c.getString(columnIndex);
c.close();
Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));
Log.w("path of image from gallery......******************.........", picturePath+"");
Toast.makeText(this,picturePath.toString(),Toast.LENGTH_LONG).show();
imageView.setImageBitmap(thumbnail);
List<ImageClassifier.Recognition> predictions = imageClassifier.recognizeImage(thumbnail, 0);
final List<String> predictionList = new ArrayList<>();
for(ImageClassifier.Recognition recog: predictions){
predictionList.add("Label: " + recog.getName() + "Confidence: " + recog.getConfidance());
}
ArrayAdapter<String> predictionsAdapter = new ArrayAdapter<>(
this,R.layout.support_simple_spinner_dropdown_item,predictionList);
listView.setAdapter(predictionsAdapter);
}catch (Exception e){
Toast.makeText(this,e.toString(),Toast.LENGTH_LONG).show();
Log.e("Error log", e.toString());
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(hasAllPermissions(grantResults)){
openCamera();
}else {
requestPermission();
}
}
private boolean hasAllPermissions(int[] grantResults) {
for(int result : grantResults){
if (result == PackageManager.PERMISSION_DENIED)
return false;
}
return true;
}
private void requestPermission() {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)){
Toast.makeText(this," Permission required",Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
}
}
private void openCamera() {
Intent camerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camerIntent,CAMERA_REQUEST_CODE);
}
private boolean hasPermission() {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
return checkSelfPermission(Manifest.permission.CAMERA)== PackageManager.PERMISSION_GRANTED;
}
return true;
}
private void selectImage() {
final CharSequence[] options = {"Take Photo", "Choose from Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Add Photo!");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
if (options[item].equals("Take Photo")) {
Intent camerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camerIntent,1);
} else if (options[item].equals("Choose from Gallery")) {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 2);
} else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
}
Note: This code snippet worked for only writing a text file and I used this method to solve
open failed: EACCES (Permission denied)
I know your Implementation has to deal with images and that is causing this 2021-01-02 11:48:03.332 9858-9858/com.example.coco_classif E/Error log: java.lang.NullPointerException: Cannot load null bitmap.
Also, check out this Exception 'open failed: EACCES (Permission denied)' on Android
I had the exact same problem, all I did was create a directory and write a text file in it.
Also, it is a good practice to create a new filename for images programmatically, use the Date formatter.
As I can see you are using an alert dialog to select images, I suggest you should not do it that way, alert dialog causes a lot of synchronization problems.
This code is tested on android Q One Plus 6t works fine without any errors.
public void generateNoteOnSD(Context context, String sFileName, String sBody) {
try {
File root = new File(String.valueOf(Environment.getExternalStorageDirectory())+"/sysInfoReports");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, sFileName);
FileWriter writer = new FileWriter(gpxfile);
writer.append(sBody);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Check you permissions
: Old storage permissions do not work on Android R.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
However, I try only when my app has a launcher property will the activity detect the NFC intent. Even if I have a intent filter in another application. Here is my manifest and both the activities. I even have foreground dispatch managed.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.melin.vustudentattendence">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".AddStudentsActivity"></activity>
<activity android:name=".AddClassesActivity" />
<activity android:name=".AddTeachersActivity" />
<activity android:name=".TestActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity android:name=".ClassAttendenceActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity
android:name=".LecutererClassesListActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity android:name=".InstituteDashboardActivity" />
<activity android:name=".TodaysClassesActivity" />
<activity
android:name=".LecturerDashboardActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".LoginActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This is my TestActivity.java
package com.melin.vustudentattendence;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ClipDescription;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class TestActivity extends AppCompatActivity {
public static final String TAG="NFCDemo";
private TextView mTextView;
private NfcAdapter mNfcAdapter;
public class NdefReaderTask extends AsyncTask<Tag,Void,String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
mTextView.setText("Read content: " + result);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mTextView=(TextView)findViewById(R.id.textView_explanation);
mNfcAdapter= NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this,"This device doesn't support NFC",Toast.LENGTH_LONG).show();
finish();
return;
}
if(!mNfcAdapter.isEnabled()){
mTextView.setText("Nfc is disabled");
}else{
mTextView.setText(R.string.explanation);
}
handleIntent(getIntent());
}
#Override
protected void onResume() {
super.onResume();
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
stopForegroundDispatch(this,mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(ClipDescription.MIMETYPE_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
private void handleIntent(Intent intent){
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (ClipDescription.MIMETYPE_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
}
and this is my ClassesAttendenceActivity
package com.melin.vustudentattendence;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ClipDescription;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class ClassAttendenceActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ClassAttendenceRowAdapter adapter;
private List<Student> students=new ArrayList<>();
private FirebaseFirestore fs;
private String incomingIntentData;
private NfcAdapter mNfcAdapter;
private static String TAG="Attendence Activity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_class_attendence);
//check nfc first
mNfcAdapter=NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this,"This device doesn't support NFC",Toast.LENGTH_LONG).show();
finish();
return;
}
if(!mNfcAdapter.isEnabled()){
Toast.makeText(this,"NFC is disabled.Please enable it",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "NFC is in reader mode", Toast.LENGTH_SHORT).show();
}
//incomingIntentData=getIntent().getExtras().getString("document");
//fs=FirebaseFirestore.getInstance();
//Toast.makeText(this,incomingIntentData,Toast.LENGTH_LONG).show();
//recyclerView=(RecyclerView)findViewById(R.id.attendenceListRecyclerView);
// LinearLayoutManager layoutManager=new LinearLayoutManager(ClassAttendenceActivity.this);
// recyclerView.setLayoutManager(layoutManager);
// populateStudentList(incomingIntentData);
handleIntent(getIntent());
}
private void populateStudentList(String url){
fs.collection(url+"/students")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Map<String,Object> data=document.getData();
Student student=new Student();
student.setStatus("ABSENT");
for (Map.Entry<String,Object> entry : data.entrySet()){
if(entry.getKey().equals("name")){
student.setName(entry.getValue().toString());
}
if(entry.getKey().equals("student_id")){
student.setStudent_id(entry.getValue().toString());
}
}
students.add(student);
Log.d("List", document.getId() + " => " + document.getData());
}
} else {
Log.d("List", "Error getting documents: ", task.getException());
}
adapter=new ClassAttendenceRowAdapter(students);
recyclerView.setAdapter(adapter);
}
});
}
public void simulatingAnIntent(){
String student_id="101";
for(Student student:students){
if(student.getStudent_id().equals(student_id)){
student.setStatus("PRESENT");
Toast.makeText(ClassAttendenceActivity.this,"Student ID"+student.getStudent_id()+"Detected",Toast.LENGTH_LONG).show();
}
}
adapter=new ClassAttendenceRowAdapter(students);
recyclerView.setAdapter(adapter);
}
#Override
protected void onResume() {
super.onResume();
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
stopForegroundDispatch(this,mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(ClipDescription.MIMETYPE_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
private void handleIntent(Intent intent){
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (ClipDescription.MIMETYPE_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
public class NdefReaderTask extends AsyncTask<Tag,Void,String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(ClassAttendenceActivity.this,"Student ID"+result+"Detected",Toast.LENGTH_LONG).show();
// for(Student student:students){
// if(student.getStudent_id().equals(result)){
// student.setStatus("PRESENT");
// Toast.makeText(ClassAttendenceActivity.this,"Student ID"+student.getStudent_id()+"Detected",Toast.LENGTH_LONG).show();
// }
// }
//
// adapter=new ClassAttendenceRowAdapter(students);
// recyclerView.setAdapter(adapter);
}
}
}
}
As you can see both the activities are almost identical
while one reads the data another doesn't
It turns out that using emulated nfc tag was the error.Using real nfc tag worked well.Though no one answered the question I am answering my own question so that when someone encounters this problem they can see this answer.Thank you.
When I try to start my IntenetService I get no errors, but it never hits the breakpoint in onHandleIntent
MainActivity.java
package com.peterchappy.filewatcher.activities;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.peterchappy.filewatcher.R;
import com.peterchappy.filewatcher.services.FileDownloadService;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class MainActivity extends Activity {
public static final String INTENT_EXTRA_FILE_URL = "URL";
private FileDownloadBroadcastReceiver broadcastReceiver;
private Button go;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
go = (Button) findViewById(R.id.go);
go.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
downloadFile("http://www.reddit.com/");
}
});
}
#Override
protected void onStart() {
super.onStart();
broadcastReceiver = new FileDownloadBroadcastReceiver();
registerReceiver(broadcastReceiver, new IntentFilter(FileDownloadService.FILE_DOWNLOADED));
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(broadcastReceiver);
}
private void downloadFile(String text) {
Intent intent = new Intent(this, FileDownloadService.class);
intent.putExtra(INTENT_EXTRA_FILE_URL, text);
this.startService(intent);
}
private void readFileAndDisplayContent(String fileName) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(openFileInput(fileName)));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
reader.close();
System.out.println(content.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
private class FileDownloadBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String localFileName = intent.getStringExtra(FileDownloadService.INTENT_LOCAL_FILE_NAME);
readFileAndDisplayContent(localFileName);
}
}
}
FileDownloadService.java
package com.peterchappy.filewatcher.services;
import android.app.IntentService;
import android.content.Intent;
import com.peterchappy.filewatcher.activities.MainActivity;
import com.peterchappy.filewatcher.helpers.FileDownloader;
public class FileDownloadService extends IntentService {
public static final String INTENT_LOCAL_FILE_NAME = "local_file_name";
public static final String FILE_DOWNLOADED = "FILE_DOWNLOADED";
public FileDownloadService() {
super("FILE_DOWNLOAD_SERVICE");
}
#Override
protected void onHandleIntent(Intent intent) {
FileDownloader fileDownloader = new FileDownloader(this);
String localFileName = fileDownloader.downloadFile(intent.getStringExtra(MainActivity.INTENT_EXTRA_FILE_URL));
Intent resultIntent = new Intent(FILE_DOWNLOADED);
resultIntent.putExtra(INTENT_LOCAL_FILE_NAME, localFileName);
sendBroadcast(resultIntent);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".activities.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>
<service android:name=".filewatcher.services.FileDownloadService"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Ok, now I think I see it in your manifest. <service> tag is outside <application> tag, try moving it inside.
I'm developing a app at the moment wich displayes a Map, your gps postition and a marker on this postition. Next Step is to recieve Data from a XML file. The XML I'm trying to use is http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=899d70a29e983f4b&lat=33.58724&lng=130.3986&range=5&order=4
But poorly after launching the app (on a real device, newest version) the app terminates and displays nothing.
LogCat says FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.xmlparser/com.example.xmlparser.MainActivitz}: java.lang.nullPointerException
MainActivity.java
package com.example.xmlparser;
import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends Activity implements LocationListener {
private TextView latituteField;
private TextView longitudeField;
private LocationManager locationManager;
private String provider;
public String url = "http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=899d70a29e983f4b&lat=33.58724&lng=130.3986&range=5&order=4";
public EditText feldname, id;
public HandleXml obj;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latituteField = (TextView) findViewById(R.id.TextView02);
longitudeField = (TextView) findViewById(R.id.TextView04);
feldname = (EditText)findViewById(R.id.editText1);
id = (EditText)findViewById(R.id.editText2);
// Get the location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the location provider -> use
// default
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null)
{
System.out.println("Provider " + provider + " has been selected.");
onLocationChanged(location);
}
else
{
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
float lat1 = (float) (location.getLatitude()); //Getting the position
float lng1 = (float) (location.getLongitude());
GoogleMap mMap;
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.fragment1)).getMap();
mMap.addMarker(new MarkerOptions()
.position(new LatLng(lat1, lng1))
.title("Your Position"));
LatLng bounds = new LatLng(lat1, lng1);
CameraUpdate cu = CameraUpdateFactory.newLatLng(bounds);
mMap.moveCamera(cu);
}
//Request updates at startup */
#Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
/* Remove the locationlistener updates when Activity is paused */
#Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
#Override
public void onLocationChanged(Location location) {
float lat = (float) (location.getLatitude()); //Getting the ' ''
float lng = (float) (location.getLongitude());
latituteField.setText(String.valueOf(lat));
longitudeField.setText(String.valueOf(lng));
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(this, "Enabled new provider " + provider,
Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(this, "Disabled provider " + provider,
Toast.LENGTH_SHORT).show();
}
public void open(View view)
{
feldname.setText(url);
obj = new HandleXml(url);
obj.fetchXML();
while(obj.parsingComplete);
feldname.setText(obj.getFeldName());
id.setText(obj.getId());
}
}
HandleXml.java
package com.example.xmlparser;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class HandleXml {
private String feldname = "name";
private String id = "id";
private String urlString = null;
private XmlPullParserFactory xmlFactoryObject;
public volatile boolean parsingComplete = true;
public HandleXml(String url)
{
this.urlString = url;
}
public String getFeldName()
{
return feldname;
}
public String getId()
{
return id;
}
public void parseXMLAndStoreIt(XmlPullParser myParser)
{
int event;
String text=null;
try
{
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT)
{
String name=myParser.getName();
switch (event)
{
case XmlPullParser.START_TAG:
break;
case XmlPullParser.TEXT:
text = myParser.getText();
break;
case XmlPullParser.END_TAG:
if(name.equals("name_kana"))
{
feldname = text;
}
else if(name.equals("id"))
{
id =text;// myParser.getAttributeValue(null,"value");
}
else
{}
break;
}
event = myParser.next();
}
parsingComplete = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void fetchXML()
{
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
try
{
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection)
url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
xmlFactoryObject = XmlPullParserFactory.newInstance();
XmlPullParser myparser = xmlFactoryObject.newPullParser();
myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES
, false);
myparser.setInput(stream, null);
parseXMLAndStoreIt(myparser);
stream.close();
} catch (Exception e)
{
e.printStackTrace();
}
}
});
thread.start();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xmlparser"
android:versionCode="1"
android:versionName="1.0" >
<permission
android:name="com.example.map.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-sdk
android:minSdkVersion="12"
android:targetSdkVersion="18" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<uses-permission android:name="com.vogella.android.locationapi.maps.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" android:debuggable="true">
<uses-library android:name="com.google.android.maps" />
<activity
android:name="com.example.xmlparser.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>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyC3DipaFNo1EC44rZ8N1AJKVAiUCNOtqZw"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
I really hope one of you can tell me whats wrong with this code as it was working perfectly fine with only the map on it's own and the parser as an own program.