Android Gotev Upload Image Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification

1

I'm creating image uploader using gotev/android-upload-service. everything work fine until choose image, and previewing image. But when I click "send" button, my app become crash with this error log

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pmb, PID: 25379
android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x42 color=0x00000000 groupKey=net.gotev vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1881)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

here my permission in AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

here my build.gradle

apply plugin: 'com.android.application'

android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
    applicationId "com.example.pmb"
    minSdkVersion 15
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'androidx.viewpager:viewpager:1.0.0'
implementation 'net.gotev:uploadservice:2.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

here my Upload.java

package com.example.pmb;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.UploadNotificationConfig;
import java.io.IOException;
import java.util.UUID;

public class Upload extends AppCompatActivity implements SingleUploadBroadcastReceiver.Delegate{

private ProgressDialog dialog;
private final SingleUploadBroadcastReceiver uploadReceiver = new SingleUploadBroadcastReceiver();


LinearLayout linear_upload;


//Declaring views
private Button buttonUpload;
private ImageView imageView;
private EditText editText;

//Image request code
private static final int PICK_IMAGE_REQUEST = 1;

//storage permission code
private static final int STORAGE_PERMISSION_CODE = 123;

//Bitmap to get image from gallery
private Bitmap bitmap;

//Uri to store the image uri
private Uri filePath;

DatePickerDialog picker;

String nama_dokumen,nopen;


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

    linear_upload = (LinearLayout)findViewById(R.id.linear_upload);

    dialog = new ProgressDialog(Upload.this);
    //Requesting storage permission
    requestStoragePermission();

    Intent pindahan = getIntent();
    nama_dokumen = pindahan.getStringExtra("nama_dokumen");
    nopen = pindahan.getStringExtra("nopen");
    getSupportActionBar().setTitle("Upload "+nama_dokumen);
    //Initializing views
    buttonUpload = (Button) findViewById(R.id.buttonUpload);
    imageView = (ImageView)findViewById(R.id.imageView);


    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showFileChooser();
        }
    });
    buttonUpload.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            buttonUpload.setVisibility(v.GONE);
            uploadMultipart();
        }
    });
}


@Override
protected void onResume() {
    super.onResume();
    uploadReceiver.register(this);
}

@Override
protected void onPause() {
    super.onPause();
    uploadReceiver.unregister(this);
}

/*
 * This is the method responsible for image upload
 * We need the full image path and the name for the image in this method
 * */
public void uploadMultipart() {
    //getting name for the image

    //getting the actual path of the image
    String path = getPath(filePath);

    //Uploading code
    try {
        String uploadId = UUID.randomUUID().toString();

        uploadReceiver.setDelegate(this);
        uploadReceiver.setUploadID(uploadId);

        //Creating a multi part request
        new MultipartUploadRequest(this, uploadId, Konfigurasi.url_dokumen_upload)
                .addFileToUpload(path, "file_dokumen") //Adding file
                .addParameter("apikey", Konfigurasi.apikey)
                .addParameter("nopen", nopen)
                .addParameter("nama_dokumen", nama_dokumen)
                .setNotificationConfig(new UploadNotificationConfig())
                .setMaxRetries(2)
                .startUpload(); //Starting the upload
    } catch (Exception exc) {
        Toast.makeText(this, "gagal upload ya "+exc.getMessage(), Toast.LENGTH_SHORT).show();
    }
}


//method to show file chooser
private void showFileChooser() {
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}

//handling the image chooser activity result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
        filePath = data.getData();
        try {
            bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
            imageView.setImageBitmap(bitmap);

            // set padding linear layout to nol
            linear_upload.setPadding(0,0,0,0);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


//method to get the file path from uri
public String getPath(Uri uri) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String document_id = cursor.getString(0);
    document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
    cursor.close();

    cursor = getContentResolver().query(
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();

    return path;
}


//Requesting permission
private void requestStoragePermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
        return;

    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
        //If the user has denied the permission previously your code will come to this block
        //Here you can explain why you need this permission
        //Explain here why you need this permission
    }
    //And finally ask for the permission
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE);
}


//This method will be called when the user will tap on allow or deny
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    //Checking the request code of our request
    if (requestCode == STORAGE_PERMISSION_CODE) {

        //If permission is granted
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //Displaying a toast
            Toast.makeText(this, "Permission granted now you can read the storage", Toast.LENGTH_LONG).show();
        } else {
            //Displaying another toast if permission is not granted
            Toast.makeText(this, "Oops you just denied the permission", Toast.LENGTH_LONG).show();
        }
    }
}

@Override
public void onProgress(int progress) {
    //your implementation
}

@Override
public void onProgress(long uploadedBytes, long totalBytes) {
    //your implementation
    dialog.setMessage("uploading...");
    dialog.show();
}

@Override
public void onError(Exception exception) {
    //your implementation
}

@Override
public void onCompleted(int serverResponseCode, byte[] serverResponseBody) {
    //your implementation
    dialog.dismiss();
    Intent mv = new Intent(Upload.this,Dokumen.class);
    mv.putExtra("nopen",nopen);
    startActivity(mv);
    finish();
}

@Override
public void onCancelled() {
    //your implementation
}
}

and here my upload.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#fff"
    tools:context=".Upload">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:background="#e1e1e1"
        android:layout_marginBottom="30dp"
        android:id="@+id/linear_upload"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/drop_image"
            android:layout_gravity="center_horizontal"
            android:adjustViewBounds="true" />
    </LinearLayout>
    <Button
        android:id="@+id/buttonUpload"
        android:layout_width="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_height="40dp"
        android:textSize="12sp"
        android:background="@color/colorAccent"
        android:textColor="#fff"
        android:paddingLeft="50dp"
        android:paddingRight="50dp"
        android:drawableLeft="@drawable/ic_kirim"
        android:drawablePadding="5dp"
        android:text="Kirim" />
    </LinearLayout>
</ScrollView>

I've trying to check on gotev github, but I found kotlin tutorial only.

how to use gotev image upload in my Upload.java or solving my problem?

java
android
file-upload
asked on Stack Overflow Dec 21, 2019 by Arif Nur Rohman • edited Dec 21, 2019 by Edric

1 Answer

0

change the dependency to newer version implementation 'net.gotev:uploadservice:3.4'

and then add NameSpace

`public class Initializer extends Application {

@Override
public void onCreate() {
    super.onCreate();
    // setup the broadcast action namespace string which will
    // be used to notify upload status.
    // Gradle automatically generates proper variable as below.
    UploadService.NAMESPACE = BuildConfig.APPLICATION_ID;
    // Or, you can define it manually.
    UploadService.NAMESPACE = "com.example.yourapp";
}

}`

In Manifest application tag add

 android:name=".Initializer"
answered on Stack Overflow Feb 29, 2020 by kishore kethineni • edited Feb 29, 2020 by kishore kethineni

User contributions licensed under CC BY-SA 3.0