i don't think so i'm going to maintain this repo but you can check flutter base stickers_internet more active there.
https://github.com/viztushar/flutter_whatsapp_stickers_internet
Join this Whatsapp group
i don't think so i'm going to maintain this repo but you can check flutter base stickers_internet more active there.
https://github.com/viztushar/flutter_whatsapp_stickers_internet
Join this Whatsapp group
thanks for you code,I want to have different contentproviders, what should I do, for both the local and the server
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 Hii bro, i want to add (Downloading please wait dialogue ) when downlaod button pressed. Coz when we click Downlaod button the app is running slow or it is not allowing users to enter sticker pack. User might feel that there is a bug.
Can you please fix that???..
I have used this project and its working fine , but only problem which i face that it continuously displaying loading message in Whatsapp sticker panel and after some time it displays stickers,
Thanks in advance
I have isue when i create json in 15pack or higher... when i download pack 1, pack 10 error/download button is not show. Please help me @virtushar.
Without downloading, stickers wont appear. Most of the users don't understand that they just leave 1 star. Instead of that, people must not able to open sticker pack without download, instesd it should download and then open. How to do that?
I run your app code and when I add a pack to whatsapp it doesn't show up there.
Can you please inspect for the reason?
Keep up great job π
i replaced value of json_link with my contents.json link.
i replaced my stickers link in contents.file ... but they are not showing plzz help
First of all, thank you very much for sharing this source code.
I want to collect these two project files in a single apk file.
Your project (sticker downloader) and this project (sticker maker): https://github.com/idoideas/stickermaker-for-whatsapp
This provides the user to create both a sticker download and a sticker in a single apk file.
The user should be able to switch to sticker package downloader and sticker maker screens with the help of nabigationdrawer or fab.
But unfortunately, I can't make single apk form two projects.
I'm getting weird bizarre mistakes.
Can you please help me make these two great projects into a single APK?
I've tried to do it many times, but I've got various actionbar and Java errors. And I know, it's very simple for you to do it. I hope you will help me.
ππI tried to, but I couldn't.πππ
https://i.hizliresim.com/P1PpXO.png
https://i.hizliresim.com/oXr2bX.jpg
Sorry for my bad English
Best regardsπ€
Could you explain why we need file.delete() in saveTrayImage and saveImage?
Thank you!
Ref:
if (file.exists()) {
file.delete();
}
I have to face this issue like When I have a test app on the Huwai device then the "Sticker:1" pack will be overridden with the "Sticker:2" pack. It means that a specific manufacture device multiple sticker pack did not work. Can you please help me to rectify this issue?
I checked
it working like boss
add documentation or i tell me how to addd sticker pack details activity to it?
now its now showing sticker publisher and etc information
Hey, public AssetFileDescriptor openAssetFile(@nonnull Uri uri, @nonnull String mode) throws FileNotFoundException this method is not called in my sticker content provider class. and i also not found any error so tell me where is the issue in my code so this method is not called??? and i also not get the last query. I only get 2content://com.viztushar.stickers.provider.StickerContentProvider/metadata/1, and 3content://com.viztushar.stickers.provider.StickerContentProvider/stickers/1 this two queryies
What are the exactly changes i need to do with this source code to build app. Thanks in advance!
Hello, im download this code and run in android studio But This Error Showing This Code..
Error contains Below.
error: cannot access DrawerLayout
class file for android.support.v4.widget.DrawerLayout not found
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.