WhatsApp / stickers

This repository contains the iOS and Android sample apps and API for creating third party sticker packs for WhatsApp.
Other
2.73k stars 1.7k forks source link

[Android] Dynamic whatsapp sticker app issue #291

Closed sagarvekariyam closed 5 years ago

sagarvekariyam commented 5 years ago

@simonzhexu I am creating an app for WhatsApp stickers and I am fetching data from the server. When a user adds a sticker to WhatsApp, it will download the sticker file into the folder. My problem is that when I download the sticker and after that set it on WhatsApp, it will give me the following error in the imagelink below https://i.stack.imgur.com/bG03J.jpg

Behavior of the app: The first time that I download the sticker and add it to the WhatsApp, it gives me the error above. However, when I remove the app from memory and reopen the app, it will work properly. Why is the app behaving like this and what is the problem?

here is my code for the StickerContentProvider.java


import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.net.Uri.Builder;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.facebook.common.util.UriUtil;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class StickerContentProvider extends ContentProvider {

static final String METADATA = "metadata";
public static final String ANDROID_APP_DOWNLOAD_LINK_IN_QUERY = "android_play_store_link";
public static Uri AUTHORITY_URI = new Builder().scheme(UriUtil.LOCAL_CONTENT_SCHEME).authority(BuildConfig.CONTENT_PROVIDER_AUTHORITY).appendPath(METADATA).build();
public static final String CONTENT_FILE_NAME = "contents.json";
public static final String IOS_APP_DOWNLOAD_LINK_IN_QUERY = "ios_app_download_link";
public static final String LICENSE_AGREENMENT_WEBSITE = "sticker_pack_license_agreement_website";
private static final UriMatcher MATCHER = new UriMatcher(-1);
private static final int METADATA_CODE = 1;
private static final int METADATA_CODE_FOR_SINGLE_PACK = 2;
public static final String PRIVACY_POLICY_WEBSITE = "sticker_pack_privacy_policy_website";
public static final String PUBLISHER_EMAIL = "sticker_pack_publisher_email";
public static final String PUBLISHER_WEBSITE = "sticker_pack_publisher_website";
static final String STICKERS = "stickers";
static final String STICKERS_ASSET = "stickers_asset";
private static final int STICKERS_ASSET_CODE = 4;
private static final int STICKERS_CODE = 3;
public static final String STICKER_FILE_EMOJI_IN_QUERY = "sticker_emoji";
public static final String STICKER_FILE_NAME_IN_QUERY = "sticker_file_name";
public static final String STICKER_PACK_ICON_IN_QUERY = "sticker_pack_icon";
public static final String STICKER_PACK_IDENTIFIER_IN_QUERY = "sticker_pack_identifier";
public static final String STICKER_PACK_NAME_IN_QUERY = "sticker_pack_name";
public static final String STICKER_PACK_PUBLISHER_IN_QUERY = "sticker_pack_publisher";
private static final int STICKER_PACK_TRAY_ICON_CODE = 5;
private String authority;
private File directory;

private List<StickerPack> stickerPackList;

@Override
public boolean onCreate() {
    authority = BuildConfig.CONTENT_PROVIDER_AUTHORITY;
    String str = authority;
    Context context = getContext();
    if (!checkFileExist()) {
        try {
            JSONObject j = new JSONObject();
            j.put("android_play_store_link", "https://play.google.com/store/apps/details?id="+getContext().getPackageName());
            JSONArray sticker = new JSONArray();
            j.put("sticker_packs", sticker);
            File file = getContext().getFilesDir();
            File content = new File(file + File.separator+"contents.json");
            content.createNewFile();
            FileWriter writer = new FileWriter(content);
            BufferedWriter bw = new BufferedWriter(writer);
            bw.write(j.toString());
            bw.close();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    context.getClass();
    if (str.startsWith(context.getPackageName())) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(getContext().getFilesDir());
        stringBuilder.append("/");
        this.directory = new File(stringBuilder.toString());
        if (!this.directory.exists()) {
            this.directory.mkdir();
        }
        MATCHER.addURI(this.authority, METADATA, 1);
        MATCHER.addURI(this.authority, "metadata/*", 2);
        MATCHER.addURI(this.authority, "stickers/*", 3);
        for (StickerPack whatsappStickerPack : getStickerPackList()) {
            StringBuilder stringBuilder2 = new StringBuilder();
            stringBuilder2.append("Stickerpack id: ");
            stringBuilder2.append(whatsappStickerPack.identifier);
            UriMatcher uriMatcher = MATCHER;
            String str2 = this.authority;
            StringBuilder stringBuilder3 = new StringBuilder();
            stringBuilder3.append("stickers_asset/");
            stringBuilder3.append(whatsappStickerPack.identifier);
            stringBuilder3.append("/");
            stringBuilder3.append(whatsappStickerPack.trayImageFile);
            uriMatcher.addURI(str2, stringBuilder3.toString(), 5);
            for (Sticker whatsappSticker : whatsappStickerPack.getStickers()) {
                UriMatcher uriMatcher2 = MATCHER;
                String str3 = this.authority;
                StringBuilder stringBuilder4 = new StringBuilder();
                stringBuilder4.append("stickers_asset/");
                stringBuilder4.append(whatsappStickerPack.identifier);
                stringBuilder4.append("/");
                stringBuilder4.append(whatsappSticker.imageFileName);
                uriMatcher2.addURI(str3, stringBuilder4.toString(), 4);
            }
        }
        return true;
    }
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("your authority (");
    stringBuilder.append(this.authority);
    stringBuilder.append(") for the content provider should start with your package name: ");
    stringBuilder.append(getContext().getPackageName());
    throw new IllegalStateException(stringBuilder.toString());
}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
    StringBuilder str = new StringBuilder();
    str.append("Query called URI: ");
    str.append(uri);
    int strArr = MATCHER.match(uri);
    System.out.println("File URI :"+uri);
    if (strArr == 1) {
        return getPackForAllStickerPacks(uri);
    }
    if (strArr == 2) {
        return getCursorForSingleStickerPack(uri);
    }
    if (strArr == 3) {
        return getStickersForAStickerPack(uri);
    }
    str = new StringBuilder();
    str.append("Unknown URI: ");
    str.append(uri);

    throw new IllegalArgumentException(str.toString());
}

@Nullable
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String str) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("Get image asset from uri: ");
    stringBuilder.append(uri);
    int str1 = MATCHER.match(uri);
    StringBuilder stringBuilder2 = new StringBuilder();
    stringBuilder2.append("Match code: ");
    stringBuilder2.append(String.valueOf(str));
    if (str1 != 4) {
        if (str1 != 5) {
            return null;
        }
    }
    return getImageAsset(uri);
}

@Nullable
@Override
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode, @Nullable CancellationSignal signal) throws FileNotFoundException {
    System.out.println("Opened File :"+uri);
    return super.openFile(uri, mode, signal);
}

@Nullable
@Override
public String getType(@NonNull Uri uri) {
    switch (MATCHER.match(uri)) {
        case 1:
            return "vnd.android.cursor.dir/vnd.stickermaker.android.stickermaker.stickercontentprovider.metadata";
        case 2:
            return "vnd.android.cursor.item/vnd.stickermaker.android.stickermaker.stickercontentprovider.metadata";
        case 3:
            return "vnd.android.cursor.dir/vnd.stickermaker.android.stickermaker.stickercontentprovider.stickers";
        case 4:
            return "image/webp";
        case 5:
            return "image/png";
        default:
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("Unknown URI: ");
            stringBuilder.append(uri);
            throw new IllegalArgumentException(stringBuilder.toString());
    }
}

private synchronized void readContentFile() {
    try {
        this.stickerPackList = ContentFileParser.parseStickerPacks(new FileInputStream(new File(this.directory, CONTENT_FILE_NAME)));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return;
}

public List<StickerPack> getStickerPackList() {
    readContentFile();
    return this.stickerPackList;
}

private Cursor getPackForAllStickerPacks(@NonNull Uri uri) {
    return getStickerPackInfo(uri, getStickerPackList());
}

private Cursor getCursorForSingleStickerPack(@NonNull Uri uri) {
    String lastPathSegment = uri.getLastPathSegment();
    for (StickerPack whatsappStickerPack : getStickerPackList()) {
        if (lastPathSegment.equals(whatsappStickerPack.identifier)) {
            return getStickerPackInfo(uri, Collections.singletonList(whatsappStickerPack));
        }
    }
    return getStickerPackInfo(uri, new ArrayList());
}

@NonNull
private Cursor getStickerPackInfo(@NonNull Uri uri, @NonNull List<StickerPack> list) {
    MatrixCursor matrixCursor = new MatrixCursor(new String[]{
            STICKER_PACK_IDENTIFIER_IN_QUERY,
            STICKER_PACK_NAME_IN_QUERY,
            STICKER_PACK_PUBLISHER_IN_QUERY,
            STICKER_PACK_ICON_IN_QUERY,
            ANDROID_APP_DOWNLOAD_LINK_IN_QUERY,
            IOS_APP_DOWNLOAD_LINK_IN_QUERY,
            PUBLISHER_EMAIL, PUBLISHER_WEBSITE,
            PRIVACY_POLICY_WEBSITE,
            LICENSE_AGREENMENT_WEBSITE});
    for (StickerPack whatsappStickerPack : list) {
        RowBuilder newRow = matrixCursor.newRow();
        newRow.add(whatsappStickerPack.identifier);
        newRow.add(whatsappStickerPack.name);
        newRow.add(whatsappStickerPack.publisher);
        newRow.add(whatsappStickerPack.trayImageFile);
        newRow.add(whatsappStickerPack.androidPlayStoreLink);
        newRow.add(whatsappStickerPack.iosAppStoreLink);
        newRow.add(whatsappStickerPack.publisherEmail);
        newRow.add(whatsappStickerPack.publisherWebsite);
        newRow.add(whatsappStickerPack.privacyPolicyWebsite);
        newRow.add(whatsappStickerPack.licenseAgreementWebsite);
    }
    matrixCursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
    return matrixCursor;
}

@NonNull
private Cursor getStickersForAStickerPack(@NonNull Uri uri) {
    String lastPathSegment = uri.getLastPathSegment();
    MatrixCursor matrixCursor = new MatrixCursor(new String[]{STICKER_FILE_NAME_IN_QUERY, STICKER_FILE_EMOJI_IN_QUERY});
    for (StickerPack whatsappStickerPack : getStickerPackList()) {
        if (lastPathSegment.equals(whatsappStickerPack.identifier)) {
            for (Sticker whatsappSticker : whatsappStickerPack.getStickers()) {
                matrixCursor.addRow(new Object[]{whatsappSticker.imageFileName, TextUtils.join(",", whatsappSticker.emojis)});
            }
        }
    }
    matrixCursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
    return matrixCursor;
}

private ParcelFileDescriptor getImageAsset(Uri uri) throws IllegalArgumentException {
    System.out.println("Image Assest URI :"+uri);
    List pathSegments = uri.getPathSegments();
    StringBuilder stringBuilder;
    if (pathSegments.size() == 3) {
        String str = (String) pathSegments.get(pathSegments.size() - 1);
        StringBuilder stringBuilder2 = new StringBuilder();
        stringBuilder2.append("File name: ");
        stringBuilder2.append(str);
        String str2 = (String) pathSegments.get(pathSegments.size() - 2);
        stringBuilder2 = new StringBuilder();
        stringBuilder2.append("Identifier: ");
        stringBuilder2.append(str2);
        if (TextUtils.isEmpty(str2)) {
            stringBuilder = new StringBuilder();
            stringBuilder.append("identifier is empty, uri: ");
            stringBuilder.append(uri);
            throw new IllegalArgumentException(stringBuilder.toString());
        } else if (TextUtils.isEmpty(str)) {
            stringBuilder = new StringBuilder();
            stringBuilder.append("file name is empty, uri: ");
            stringBuilder.append(uri);
            throw new IllegalArgumentException(stringBuilder.toString());
        } else {
            for (StickerPack whatsappStickerPack : getStickerPackList()) {
                if (str2.equals(whatsappStickerPack.identifier)) {
                    if (str.equals(whatsappStickerPack.trayImageFile)) {
                        return fetchFile(uri, str, str2);
                    }
                    for (Sticker whatsappSticker : whatsappStickerPack.getStickers()) {
                        if (str.equals(whatsappSticker.imageFileName)) {
                            return fetchFile(uri, str, str2);
                        }
                    }
                    continue;
                }
            }
            return null;
        }
    }
    stringBuilder = new StringBuilder();
    stringBuilder.append("path segments should be 3, uri is: ");
    stringBuilder.append(uri);

    throw new IllegalArgumentException(stringBuilder.toString());
}

private ParcelFileDescriptor fetchFile(@NonNull Uri uri, @NonNull String str, @NonNull String str2) {
    try {
        File file = this.directory;
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str2);
        stringBuilder.append("/");
        stringBuilder.append(str);
        return ParcelFileDescriptor.open(new File(file, stringBuilder.toString()), 268435456);
    } catch (FileNotFoundException e) {
        str2.getClass();
        str2 = getContext().getPackageName();
        StringBuilder stringBuilder2 = new StringBuilder();
        stringBuilder2.append("IOException when getting asset file, uri:");
        stringBuilder2.append(uri);
        return null;
    }
}

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
    throw new UnsupportedOperationException("Not supported");
}

@Override
public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
    throw new UnsupportedOperationException("Not supported");
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
    /*StringBuilder str = new StringBuilder();
    str.append("Sticker pack count: ");
    str.append(getStickerPackList().size());
    for (StickerPack whatsappStickerPack : getStickerPackList()) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Stickerpack iddd: ");
        stringBuilder.append(whatsappStickerPack.identifier);
        UriMatcher strArr = MATCHER;
        String str2 = this.authority;
        StringBuilder stringBuilder2 = new StringBuilder();
        stringBuilder2.append("stickers_asset/");
        stringBuilder2.append(whatsappStickerPack.identifier);
        stringBuilder2.append("/");
        stringBuilder2.append(whatsappStickerPack.trayImageFile);
        strArr.addURI(str2, stringBuilder2.toString(), 5);
        for (Sticker whatsappSticker : whatsappStickerPack.getStickers()) {
            UriMatcher uriMatcher = MATCHER;
            String str3 = this.authority;
            StringBuilder stringBuilder3 = new StringBuilder();
            stringBuilder3.append("stickers_asset/");
            stringBuilder3.append(whatsappStickerPack.identifier);
            stringBuilder3.append("/");
            stringBuilder3.append(whatsappSticker.imageFileName);
            uriMatcher.addURI(str3, stringBuilder3.toString(), 4);
        }
    }
    getContext().getContentResolver().notifyChange(uri, null);*/
    return 0;
}

public boolean checkFileExist () {
    boolean exist = false;
    File file = getContext().getFilesDir();
    File content = new File(file, "contents.json");
    if (content.exists()) {
        exist = true;
    } else {
        exist = false;
    }
    return exist;
}
 } ```

Here is code for adding sticker to the whatsapp app

 Intent intent = new Intent();
            //noinspection SpellCheckingInspection
            intent.setAction("com.whatsapp.intent.action.ENABLE_STICKER_PACK");
            intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_ID, downloadpack.name);
            intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_AUTHORITY, BuildConfig.CONTENT_PROVIDER_AUTHORITY);
            intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_NAME, downloadpack.name);
            try {
                startActivityForResult(intent, StickerPackDetailsActivity.ADD_PACK);
            } catch (ActivityNotFoundException e) {
                Toast.makeText(StickerPackListActivity.this, R.string.error_adding_sticker_pack, Toast.LENGTH_LONG).show();
            }
geekmentors commented 5 years ago

@sagarvekariyam Has the issue resolved? Where is the code where you are fetching the images from Internet?

viztushar commented 5 years ago

you need to pass the sticker id not the sticker name in the intent. you need to change this line:-

intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_ID, downloadpack.name);

to

intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_ID, downloadpack.identifier);

pansuriyasumit commented 5 years ago

Override the sticker pack with Old sticker pack issue in android. How can I solve it? Any one have faced this issue, help me!

piyushbhanu commented 5 years ago

@sagarvekariyam can you please help me with where and how should I add my server url? can you share me your application?

adityaspt commented 4 years ago

Is this issue solved ?

worstkiller commented 4 years ago

@sagarvekariyam, @ahkohd, @piyushbhanu Hey guys, can you tell me the approach you are using for the downloading and inserting into the content provider. I'm able to download the icon packs to my internal storage but not sure what next has to be done. As the given example shows getting icons pack from assets folder. Any suggestion or sample code help will be highly appreciated Thanks