Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stickers are disappearing some times when creating packs in runtime #13

Open
vrsrohit opened this issue Jan 19, 2019 · 1 comment
Open

Comments

@vrsrohit
Copy link

vrsrohit commented Jan 19, 2019

Hello I am trying to load stickers from server , I am saving them in internal storage and changed the content provider to suit my requirement but the problem here is when I tried to add 5 sticker packs only 2/3 are reflecting correctly in WhatsApp and they are loading very slowly . (sometimes all packs will show in WhatsApp but fail to display stickers if in case it displays stickers when i clear the app from background then they will disappear )
I have taken provider from your code only and made some changes
Here I have pasted my ContentProvider. Please Help !!

PS :: I have switched of battery optimisation for the app and tested in 4 different type of mobiles.
`package com.dsrtech.whatsappstickers.Whatsapp;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;

import com.dsrtech.whatsappstickers.BuildConfig;
import com.dsrtech.whatsappstickers.utils.NewImageSaver;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class StickerContentProvider extends ContentProvider {

/**
 * Do not change the strings listed below, as these are used by WhatsApp. And changing these will break the interface between sticker app and WhatsApp.
 */
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";
public static final String STICKER_PACK_ICON_IN_QUERY = "sticker_pack_icon";
public static final String ANDROID_APP_DOWNLOAD_LINK_IN_QUERY = "https://play.google.com/store/apps/details?id=com.dsrtech.cutpasteeditor&hl=en";
public static final String IOS_APP_DOWNLOAD_LINK_IN_QUERY = "ios_app_download_link";
public static final String PUBLISHER_EMAIL = "sticker_pack_publisher_email";
public static final String PUBLISHER_WEBSITE = "sticker_pack_publisher_website";
public static final String PRIVACY_POLICY_WEBSITE = "sticker_pack_privacy_policy_website";
public static final String LICENSE_AGREENMENT_WEBSITE = "sticker_pack_license_agreement_website";

public static final String STICKER_FILE_NAME_IN_QUERY = "sticker_file_name";
public static final String STICKER_FILE_EMOJI_IN_QUERY = "sticker_emoji";

public static final String CONTENT_SCHEME = "content";
static final String METADATA = "metadata";
static final String STICKERS = "stickers";
static final String STICKERS_ASSET = "stickers_asset";
private static final String TAG = StickerContentProvider.class.getSimpleName();
/**
 * Do not change the values in the UriMatcher because otherwise, WhatsApp will not be able to fetch the stickers from the ContentProvider.
 */
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int METADATA_CODE = 1;
private static final int METADATA_CODE_FOR_SINGLE_PACK = 2;
private static final int STICKERS_CODE = 3;
private static final int STICKERS_ASSET_CODE = 4;
private static final int STICKER_PACK_TRAY_ICON_CODE = 5;
public static Uri AUTHORITY_URI = new Uri.Builder().scheme(StickerContentProvider.CONTENT_SCHEME).authority(BuildConfig.CONTENT_PROVIDER_AUTHORITY).appendPath(StickerContentProvider.METADATA).build();
private List<StickerPack> stickerPackList = new ArrayList<>();
private static final String LOGTAG = "Whatsapp_status";


@Override
public boolean onCreate() {
    final String authority = BuildConfig.CONTENT_PROVIDER_AUTHORITY;
    if (!authority.startsWith(Objects.requireNonNull(getContext()).getPackageName())) {
        throw new IllegalStateException("your authority (" + authority + ") for the content provider should start with your package name: " + getContext().getPackageName());
    }

    //the call to get the metadata for the sticker packs.
    MATCHER.addURI(authority, METADATA, METADATA_CODE);

    //the call to get the metadata for single sticker pack. * represent the identifier
    MATCHER.addURI(authority, METADATA + "/*", METADATA_CODE_FOR_SINGLE_PACK);

    //gets the list of stickers for a sticker pack, * respresent the identifier.
    MATCHER.addURI(authority, STICKERS + "/*", STICKERS_CODE);

    for (StickerPack stickerPack : getStickerPackList()) {
        Log.e(TAG, "onCreate: " + stickerPack.identifier);
        MATCHER.addURI(authority, STICKERS_ASSET + "/" + stickerPack.identifier + "/" + stickerPack.trayImageFile, STICKER_PACK_TRAY_ICON_CODE);
        if (stickerPack.getStickers() != null) {
            for (Sticker sticker : stickerPack.getStickers()) {
                MATCHER.addURI(authority, STICKERS_ASSET + "/" + stickerPack.identifier + "/" + sticker.imageFileName, STICKERS_ASSET_CODE);
            }

        }
    }

    return true;
}

@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, String selection,
                    String[] selectionArgs, String sortOrder) {
    final int code = MATCHER.match(uri);
    Log.d(TAG, "query: " + code + uri);
    if (code == METADATA_CODE) {
        return getPackForAllStickerPacks(uri);
    } else if (code == METADATA_CODE_FOR_SINGLE_PACK) {
        return getCursorForSingleStickerPack(uri);
    } else if (code == STICKERS_CODE) {
        return getStickersForAStickerPack(uri);
    } else {
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

@Nullable
@Override
public AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode) {
    MATCHER.match(uri);
    final int matchCode = MATCHER.match(uri);
    final List<String> pathSegments = uri.getPathSegments();
    Log.d(TAG, "openFile: " + matchCode + uri + "\n" + uri.getAuthority()
            + "\n" + pathSegments.get(pathSegments.size() - 3) + "/"
            + "\n" + pathSegments.get(pathSegments.size() - 2) + "/"
            + "\n" + pathSegments.get(pathSegments.size() - 1));

    return getImageAsset(uri);
}

private AssetFileDescriptor getImageAsset(Uri uri) throws IllegalArgumentException {
    final List<String> pathSegments = uri.getPathSegments();
    if (pathSegments.size() != 3) {
        throw new IllegalArgumentException("path segments should be 3, uri is: " + uri);
    }
    String fileName = pathSegments.get(pathSegments.size() - 1);
    final String identifier = pathSegments.get(pathSegments.size() - 2);
    if (TextUtils.isEmpty(identifier)) {
        throw new IllegalArgumentException("identifier is empty, uri: " + uri);
    }
    if (TextUtils.isEmpty(fileName)) {
        throw new IllegalArgumentException("file name is empty, uri: " + uri);
    }
    for (StickerPack stickerPack : getStickerPackList()) {
        if (identifier.equals(stickerPack.identifier)) {
            if (fileName.equals(stickerPack.trayImageFile)) {
                return fetchFile(uri, fileName, identifier);
            } else {
                for (Sticker sticker : stickerPack.getStickers()) {
                    if (fileName.equals(sticker.imageFileName)) {
                        return fetchFile(uri, fileName, identifier);
                    }
                }
            }
        }
    }
    return null;
}

private AssetFileDescriptor fetchFile(@NonNull Uri uri, @NonNull String fileName, @NonNull String identifier) {
    Log.i(LOGTAG," + fetchfile called"+fileName +" + "+ identifier);
    try {
        File file;
        file = new NewImageSaver(getContext()).loadFile("whatsapp_stickers" + identifier, fileName);
        if (!file.exists()) {
            Log.i(LOGTAG," + fetchfile file not exists");
        }
        Log.i(LOGTAG," + fetchfile file exists");
        //working one
        //return new AssetFileDescriptor(ParcelFileDescriptor.open(file, MODE_READ_ONLY), 0L, -1L);
        //edited by me
        return new AssetFileDescriptor(ParcelFileDescriptor.open(file, MODE_READ_ONLY), 0L, file.length());
    } catch (IOException e) {
        Log.e(Objects.requireNonNull(getContext()).getPackageName(), "IOException when getting asset file, uri:" + uri, e);
        return null;
    }
}
@Override
public String getType(@NonNull Uri uri) {
    final int matchCode = MATCHER.match(uri);
    switch (matchCode) {
        case METADATA_CODE:
            return "vnd.android.cursor.dir/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + METADATA;
        case METADATA_CODE_FOR_SINGLE_PACK:
            return "vnd.android.cursor.item/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + METADATA;
        case STICKERS_CODE:
            return "vnd.android.cursor.dir/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + STICKERS;
        case STICKERS_ASSET_CODE:
            return "image/webp";
        case STICKER_PACK_TRAY_ICON_CODE:
            return "image/png";
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

public List<StickerPack> getStickerPackList() {
    Log.i(LOGTAG," + getStickerPackList Called");
    stickerPackList.clear();
    for (int i = 1 ; i<=new NewImageSaver(getContext()).loadMainFolderSize();i++ ){
        StickerPack mStickerPack = new StickerPack(String.valueOf(i), "PixelPack"+i, "PixelForce", "tray_Cuppy.png", "", "", "", "");
        ArrayList<Sticker> mStickers = new ArrayList<>();
        List<String> mEmojis = new ArrayList<>();
        String str = getEmojiByUnicode(0x1F60A);
        mEmojis.add(str);
        mEmojis.add(str);

        for (int j = 0; j < new NewImageSaver(getContext()).loadFileNames("whatsapp_stickers"+i).size(); j++) {
            String name = new NewImageSaver(getContext()).loadFileNames("whatsapp_stickers"+i).get(j);
            Log.i(LOGTAG," + getStickerPackList adding sticker + "+name);
            if (!name.equals("tray_Cuppy.png")) {
                mStickers.add(new Sticker(name, mEmojis));
            }
        }
        mStickerPack.setStickers(mStickers);
        stickerPackList.add(mStickerPack);
    }
    Log.i(LOGTAG," + getStickerPackList size + "+stickerPackList.size());
    //stickerPackList.add(new CustomSaverNew().RetriveObject("stickerpack1",getContext(),"stickerpack1"));
    return stickerPackList;

}

public String getEmojiByUnicode(int unicode) {
    return new String(Character.toChars(unicode));
}

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

private Cursor getCursorForSingleStickerPack(@NonNull Uri uri) {
    final String identifier = uri.getLastPathSegment();
    for (StickerPack stickerPack : getStickerPackList()) {
        if (Objects.requireNonNull(identifier).equals(stickerPack.identifier)) {
            return getStickerPackInfo(uri, Collections.singletonList(stickerPack));
        }
    }

    return getStickerPackInfo(uri, new ArrayList<>());
}

@NonNull
private Cursor getStickerPackInfo(@NonNull Uri uri, @NonNull List<StickerPack> stickerPackList) {
    MatrixCursor cursor = 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 stickerPack : stickerPackList) {
        MatrixCursor.RowBuilder builder = cursor.newRow();
        builder.add(stickerPack.identifier);
        builder.add(stickerPack.name);
        builder.add(stickerPack.publisher);
        builder.add(stickerPack.trayImageFile);
        builder.add(stickerPack.androidPlayStoreLink);
        builder.add(stickerPack.iosAppStoreLink);
        builder.add(stickerPack.publisherEmail);
        builder.add(stickerPack.publisherWebsite);
        builder.add(stickerPack.privacyPolicyWebsite);
        builder.add(stickerPack.licenseAgreementWebsite);
    }
    Log.d(LOGTAG, "getStickerPackInfo: " + stickerPackList.size());
    cursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
    return cursor;
}

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

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

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

@Override
public int update(@NonNull Uri uri, ContentValues values, String selection,
                  String[] selectionArgs) {
    throw new UnsupportedOperationException("Not supported");
}

}
`

@viztushar
Copy link
Owner

@vrsrohit your ContentProvider provider is not providing file to the whatsapp or check your stickers location is same as your provider location url.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants