从 Google Play 但不是从 Android Studio 运行时出现 NullPointerException

Posted

技术标签:

【中文标题】从 Google Play 但不是从 Android Studio 运行时出现 NullPointerException【英文标题】:NullPointerException when running from Google Play but not from Android Studio 【发布时间】:2018-10-05 23:05:54 【问题描述】:

我遇到了一个大问题,我不知道发生了什么,我已经将一个应用程序上传到 Play 商店,因为当我在模拟器甚至我的真实设备上运行它时,它并没有崩溃,但是现在当我从 Google Play 下载它时,它说:

java.lang.NullPointerException: 
  at com..onBindViewHolder (ChooseCard.java)
  or                     .onCreateViewHolder (ChooseCard.java)
  at com..onBindViewHolder (ChooseCard.java)
  or                     .onCreateViewHolder (ChooseCard.java)
  at com.firebase.ui.database.FirebaseRecyclerAdapter.getItemCount (FirebaseRecyclerAdapter.java)
  or                     .onBindViewHolder (FirebaseRecyclerAdapter.java)
  or                     .onChildChanged (FirebaseRecyclerAdapter.java)
  or                     .onError (FirebaseRecyclerAdapter.java)
  at com.yarolegovich.discretescrollview.InfiniteScrollAdapter.access$100 (InfiniteScrollAdapter.java)
  or                     .getItemCount (InfiniteScrollAdapter.java)
  or                     .getItemViewType (InfiniteScrollAdapter.java)
  or                     .onAttachedToRecyclerView (InfiniteScrollAdapter.java)
  or                     .onBindViewHolder (InfiniteScrollAdapter.java)
  or                     .onCreateViewHolder (InfiniteScrollAdapter.java)
  or                     .wrap (InfiniteScrollAdapter.java)

这个问题已经好几天了,我找不到它,请你帮帮我吗?

这是我的build.gradle 实现

implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation 'com.android.support:design:27.1.1'
implementation 'com.intuit.sdp:sdp-android:1.0.4'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.google.firebase:firebase-core:15.0.0'
implementation 'com.google.firebase:firebase-auth:15.0.0'
implementation 'com.google.android.gms:play-services-auth:15.0.0'
implementation 'com.google.firebase:firebase-database:15.0.0'
implementation 'com.anjlab.android.iab.v3:library:1.0.44'
implementation 'com.firebaseui:firebase-ui-database:3.3.1'
implementation 'com.onesignal:OneSignal:3.7.1'
implementation 'com.yarolegovich:discrete-scrollview:1.3.2'
implementation 'com.pranavpandey.android:dynamic-toasts:0.9.0'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.11'
implementation 'com.google.android.gms:play-services-analytics:15.0.0'
.....
 dependencies 
        classpath 'com.android.tools.build:gradle:3.1.2'
        classpath 'com.google.gms:google-services:3.2.1'

编辑

我已经在 Google Play 上更新了我的应用程序,但没有任何反应,仍然在同一个 Activity 上崩溃,我现在知道如何调试它,问题是当我在模拟器上从 Google Play 下载应用程序时(即使在新的模拟器设备上也不会崩溃)和在我的真实设备上。

正如@Marcos Vascondelos 所说,我做了 Build > Genreate Signed APK > get the app-release.apk 在我的设备上安装它,问题是我无法登录它是这个方法:

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) 
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            try 
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = task.getResult(ApiException.class);
                firebaseAuthWithGoogle(account);
             catch (ApiException e) 
                // Google Sign In failed, update UI appropriately
                Log.w(TAG, "Google sign in failed", e.getCause());
                Toast with e.getCause is null
            
        
    

如果你想看看我如何登录而不是在这个问题上添加更多代码,我在这个GitHubGist

我读过可能是 SHA-1 的问题,但我不知道为什么在模拟器上没问题,设备没问题,Google play 也没问题,但是如果我直接安装 .apk,它会显示为空。

最后编辑

我发现问题不在Firebase 调用上,而是在填充列表上,我的意思是产品被正确捕获,但是当我尝试放入列表时它崩溃了

我的FirebaseRecyclerOptions 适配器看起来像

 final FirebaseRecyclerOptions< CardPOJO > options =
                    new FirebaseRecyclerOptions.Builder< CardPOJO >()
                            .setQuery(products_ref, CardPOJO.class)
                            .build();



            adapter = new   FirebaseRecyclerAdapter< CardPOJO, CardHolder>(options) 
                @Override
                public CardHolder onCreateViewHolder(ViewGroup parent, int viewType) 
                    //inflate the single recycler view layout(item)
                    View view = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.card_product, parent, false);
                    final CardHolder cardViewHolder = new CardHolder(view);
                    return cardViewHolder;
                



                @Override
                public void onDataChanged() 
                    super.onDataChanged();
                    if(progressDialog!=null)progressDialog.dismiss();initViews();
                


                @Override
                protected void onBindViewHolder(final CardHolder holder, int position, final CardPOJO model) 
                    holder.itemView.setSelected(0== position); ////where you are in the list
                    holder.getLayoutPosition();
                    switch (model.getState())
                        case "free":
                            holder.card_image.setImageResource();
                            break;
                        case "not_free":
                            if(userOwnsProduct(model.getProduct_id()))
                                holder.card_image.setImageResource();
                            
                            else
                                holder.card_image.setImageResource();
                            

                            break;
                        default:
                            break;
                    
                    holder.view.setOnClickListener(new View.OnClickListener() 
                        @Override
                        public void onClick(View v) 
                            if(model.getState().equals("free"))
                                //normal stuff1

                            
                            else
                                if (!readyToPurchase) 
                                    DynamicToast.makeError(mContext,"Problems with Google Play",Toast.LENGTH_SHORT).show();
                                    return;
                                
                                root_ref.child("PurchasedProducts").child(currentUser).addValueEventListener(new ValueEventListener() 
                                    @Override
                                    public void onDataChange(DataSnapshot dataSnapshot) 
                                        if(dataSnapshot.hasChild(model.getProduct_id()))
                                            //Normal stuff
                                        
                                        else
                                            bp.purchase((Activity) mContext,model.getProduct_id());
                                        
                                    

                                    @Override
                                    public void onCancelled(DatabaseError databaseError) 

                                    
                                );

                            

                        
                    );


                

            ;
            adapter.startListening();



            infiniteAdapter = InfiniteScrollAdapter.wrap(adapter);
            itemPicker.setAdapter(infiniteAdapter);
            //.setItemTransitionTimeMillis(DiscreteScrollViewOptions.getTransitionTime());
            itemPicker.setItemTransformer(new ScaleTransformer.Builder()
                    .setMinScale(0.5f)
                    .build());

【问题讨论】:

but now when I download it from Google Play 去什么? Have a look at this thread @greenapps 到真实设备或模拟器,在此之前他是直接从 Android Studio 做的 如果您想查看从 Firebase 实时数据库获取数据并使用 FirebaseRecyclerAdapter 将其显示在 RecyclerView 中的正确方法,this 就是您的方式可以的。 您应该使用 firebase-ui-database:3.3.1 以与 Firebase SDK 15.0.0 兼容。 【参考方案1】:

记住,总是检查组件是否为空。比执行你的代码。 示例:

if ("your_component" != null)
//your code

【讨论】:

【参考方案2】:

您似乎已经尝试了我能想到的几乎所有方法。这可能是 SHA-1 的问题。试试这些:

首先,检查你正在访问的孩子是否真的存在。(即不为空) 尝试检查您是否确实有权添加产品。另外,请检查 Firebase 规则。 尝试添加具有不同类型用户的产品(如果您的应用包含不同类型的用户)。

【讨论】:

测试它并且它工作......问题是尝试将数据放入recyclerView时 @IshanFernando 我猜有问题,否则我会再次上传 @IshanFernando 用适配器代码编辑了我的问题 @Skizo-ozᴉʞS 你能告诉我们它崩溃的地方吗?如果没有,那很好。还有一件事:在模型上调用 get 方法之前,您是否可以检查是否设置了产品详细信息和 id?【参考方案3】:

好的,这就去!我看到代码有一个异常可能被忽略,就像在高端 apis 中一样。简单来说,api 23 和 >23 就像在 viewHolder 区域中使用 ViewGroup Parent 获取上下文一样!没问题,但在小型 api 设备上我认为这将是一个问题!

所以试试这个希望这会有所帮助!

也许我是从这个角度看的,希望对你有帮助

public CardHolder onCreateViewHolder(ViewGroup parent, int viewType) 
                                //inflate the single recycler view layout(item)
                           //  !!!!!!!!!!!!! **the issue is here**! !!!!!!!!!!!!!!!
                                View view = LayoutInflater.from(parent.getContext())
                                        .inflate(R.layout.card_product, parent, false);
                                final CardHolder cardViewHolder = new CardHolder(view);
                                return cardViewHolder;
                            

您的布局没有正确膨胀!像这样获取上下文可能是该类出现NULL POINTER EXCEPTION的原因!有一个简单的方法来做到这一点!比如通过在实例化时使用适配器的构造函数获取活动的上下文。

这是一个例子!

public class yourActivity extends AppCompatActivity
   YourAdapter mAdapter; 
/// lets say you are setting it up in android ONCREATE Method
@override
public void OnCreate(....)
...........

mAdapter(data,design,YourActivity.this);
 //here this will be the context going in your adapter simple




在您的适配器的构造函数中,您可以将其存储在一个全局变量中,可能是这样的

public class YourAdapter extends RECYCLERView.Adapter......
Context mContext;
public YourAdapter(Data data, int design,Context mContext)
this.mContext = mContext;

//and now you can access without any stress about context null exception 
   public CardHolder onCreateViewHolder(ViewGroup parent, int viewType) 
                            //inflate the single recycler view layout(item)
                            View view = LayoutInflater.from(mContext)
                                    .inflate(R.layout.card_product, parent, false);
                            final CardHolder cardViewHolder = new CardHolder(view);
                            return cardViewHolder;
                        

上面的代码暴露并解决了第一个异常。我希望的第二个是这样的

您正在尝试使用 RecyclerView,但没有为它提供用于保存视图的子类!

当我们为回收器视图制作适配器时,必然会有 ViewHolder 的子类为我们做简单的回收。该子类的主要工作是保存视图并使用它们的 id 找到它们

对于一般示例,试试这个 link 我找到了!归功于 git writer。

【讨论】:

所以你说的是两种方法,对吧? parent.getContext() 并将上下文本身传递给构造函数? parent.getContext 不起作用,这是这里异常的主要原因!尝试改变获取上下文的方式,我希望会奏效 但是我有这样的适配器: adapter = new FirebaseRecyclerAdapter(options) @Override public CardHolder onCreateViewHolder(ViewGroup parent, int viewType) //膨胀单个回收器视图布局( item) 视图视图 = LayoutInflater.from(parent.getContext()) .inflate(R.layout.card_product, parent, false);返回新的持卡人(视图); 如何通过参数传递上下文? 创建一个新类扩展它的 FirebaseRecyclerAdapter 并尝试在那里创建构造函数^_^【参考方案4】:

问题是在使用Proguard 时,我没有在我的pojo 类上使用@Keep,所以当尝试使用firebase 序列化类时,数据库没有找到属性,因为它们被混淆了。

【讨论】:

我面临着完全相同的问题。你在哪里使用@Keep?在使用 firebase 数据库的整个 Fragment 上? 欢迎提出新问题并添加信息,以便我查看:) 同样的问题!!我试图从 wordpress 获取数据,它可以在我的手机上运行(从我的笔记本电脑上运行时),但当我将其上传到 Google Play 时却不行

以上是关于从 Google Play 但不是从 Android Studio 运行时出现 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

Google Play 游戏排行榜发布分数报告成功但不更新

如何知道应用程序是从 google play 还是侧载安装的?

NetSuite 如何免Google Play取得安装包

谷歌地图地理编码从浏览器工作,但不是从 PHP 服务器

如果应用是从 Google Play 商店下载的,Android 应用是不是只会收到推送通知? (反应原生博览会)

已发布的应用在 google play 上显示不同的签名