代码之家  ›  专栏  ›  技术社区  ›  codproe

安装Android后我无法打开应用程序

  •  0
  • codproe  · 技术社区  · 1 年前

    我正在开发我的第一个用于工作时间跟踪的Android应用程序。

    MainActivity.java:

    package com.example;
    import com.example.work.R;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import androidx.appcompat.app.AppCompatActivity;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    public class MainActivity extends AppCompatActivity {
    
        private TextView startTimeTextView, endTimeTextView, todayTimeTextView, weekTimeTextView;
        private Button startWorkButton, endWorkButton, resetWeekButton, showHelpButton;
        private boolean working = false;
        private long startTime = 0, endTime = 0;
        private float[] workTimes = new float[7];  // Array to store weekly work times
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            startTimeTextView = findViewById(R.id.startTimeTextView);
            endTimeTextView = findViewById(R.id.endTimeTextView);
            todayTimeTextView = findViewById(R.id.todayTimeTextView);
            weekTimeTextView = findViewById(R.id.weekTimeTextView);
            startWorkButton = findViewById(R.id.startWorkButton);
            endWorkButton = findViewById(R.id.endWorkButton);
            resetWeekButton = findViewById(R.id.resetWeekButton);
            showHelpButton = findViewById(R.id.showHelpButton);
    
            startWorkButton.setOnClickListener(view -> startWork());
            endWorkButton.setOnClickListener(view -> endWork());
            resetWeekButton.setOnClickListener(view -> resetWeek());
            showHelpButton.setOnClickListener(view -> showHelp());
    
            loadWorkTimes();  // Load work times from storage
    
            updateUI();  // Update UI with loaded data
        }
    
        private void startWork() {
            if (working) {
                startTime = System.currentTimeMillis();  // Record start time in milliseconds
                startTimeTextView.setText("Start Time: " + formatTime(startTime));
            } else {
                startTime = System.currentTimeMillis();  // Begin initial work session
                startTimeTextView.setText("Start Time: " + formatTime(startTime));
                endTime = 0;  // Reset end time on new session
                endTimeTextView.setText("End Time: ");
            }
            working = true;  // Set working status to true
            saveWorkingStatus();  // Save working status
            updateUI();
        }
    
        private void endWork() {
            if (!working) {
                endTimeTextView.setText("You haven't started working yet!");
                return;
            }
            endTime = System.currentTimeMillis();  // Record end time in milliseconds
            float workDuration = (endTime - startTime) / 3600000.0f;  // Convert milliseconds to hours
            int dayOfWeek = getDayOfWeek();
            workTimes[dayOfWeek] += workDuration;  // Add work duration to the respective day
            saveWorkTimes();  // Save updated work times
            updateUI();
            working = false;  // Reset working status
            saveWorkingStatus();  // Save working status
            endTimeTextView.setText("End Time: " + formatTime(endTime));
        }
    
        private void resetWeek() {
            for (int i = 0; i < workTimes.length; i++) {
                workTimes[i] = 0;  // Reset work times to zero
            }
            saveWorkTimes();  // Save reset work times
            updateUI();
        }
    
        private void showHelp() {
            // Show help dialog or message
            new android.app.AlertDialog.Builder(this)
                    .setTitle("Help")
                    .setMessage("All commands:\n- Start Work: Start working session.\n- End Work: End working session.\n- Reset Week: Reset weekly work times.")
                    .setPositiveButton("OK", null)
                    .show();
        }
    
        private void updateUI() {
            StringBuilder weekText = new StringBuilder();
            weekText.append("Today: ").append(String.format(Locale.US, "%.3fh", workTimes[getDayOfWeek()])).append("\n");
            float weekTotal = 0;
            for (int i = 0; i < 7; i++) {
                weekText.append("Day ").append(i).append(": ").append(String.format(Locale.US, "%.3fh", workTimes[i])).append("\n");
                weekTotal += workTimes[i];
            }
            weekText.append("Week: ").append(String.format(Locale.US, "%.3fh", weekTotal)).append("\n");
            weekTimeTextView.setText(weekText.toString());
    
            if (startTime > 0) {
                startTimeTextView.setText("Start Time: " + formatTime(startTime));
            }
            if (endTime > 0) {
                endTimeTextView.setText("End Time: " + formatTime(endTime));
            }
        }
    
        private String formatTime(long timeInMillis) {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.US);
            return sdf.format(new Date(timeInMillis));
        }
    
        private int getDayOfWeek() {
            return (int) ((System.currentTimeMillis() / (1000 * 60 * 60 * 24)) % 7);  // Calculate day of week from milliseconds
        }
    
        private void saveWorkTimes() {
            getSharedPreferences("workTimesPrefs", MODE_PRIVATE).edit().putString("workTimes", serializeWorkTimes()).apply();
        }
    
        private String serializeWorkTimes() {
            StringBuilder sb = new StringBuilder();
            for (float time : workTimes) {
                sb.append(time).append(",");
            }
            return sb.toString();
        }
    
        private void loadWorkTimes() {
            String workTimesString = getSharedPreferences("workTimesPrefs", MODE_PRIVATE).getString("workTimes", "0,0,0,0,0,0,0");
            String[] workTimesArray = workTimesString.split(",");
            for (int i = 0; i < workTimesArray.length; i++) {
                workTimes[i] = Float.parseFloat(workTimesArray[i]);
            }
        }
    
        private void saveWorkingStatus() {
            getSharedPreferences("workingPrefs", MODE_PRIVATE).edit().putBoolean("working", working).apply();
        }
    }
    

    activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">
    
        <TextView
            android:id="@+id/titleTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Work Time Tracker"
            android:textSize="24sp"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="16dp"/>
    
        <TextView
            android:id="@+id/startTimeTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Time: "
            android:layout_below="@+id/titleTextView"
            android:layout_marginBottom="8dp"
            android:layout_centerHorizontal="true"/>
    
        <TextView
            android:id="@+id/endTimeTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="End Time: "
            android:layout_below="@+id/startTimeTextView"
            android:layout_marginBottom="8dp"
            android:layout_centerHorizontal="true"/>
    
        <TextView
            android:id="@+id/todayTimeTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Today: 0.000h"
            android:layout_below="@+id/endTimeTextView"
            android:layout_marginBottom="8dp"
            android:layout_centerHorizontal="true"/>
    
        <TextView
            android:id="@+id/weekTimeTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Week: 0.000h"
            android:layout_below="@+id/todayTimeTextView"
            android:layout_centerHorizontal="true"/>
    
        <Button
            android:id="@+id/startWorkButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Work"
            android:layout_below="@+id/weekTimeTextView"
            android:layout_marginTop="16dp"
            android:layout_centerHorizontal="true"/>
    
        <Button
            android:id="@+id/endWorkButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="End Work"
            android:layout_below="@+id/startWorkButton"
            android:layout_marginTop="8dp"
            android:layout_centerHorizontal="true"/>
    
        <Button
            android:id="@+id/resetWeekButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Reset Week"
            android:layout_below="@+id/endWorkButton"
            android:layout_marginTop="8dp"
            android:layout_centerHorizontal="true"/>
    
        <Button
            android:id="@+id/showHelpButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Help"
            android:layout_below="@+id/resetWeekButton"
            android:layout_marginTop="8dp"
            android:layout_centerHorizontal="true"/>
    </RelativeLayout>
    

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.Work"
            tools:targetApi="31" />
    
    </manifest>
    

    我没有得到任何错误,我能够成功地构建apk文件。然而,当我在Android设备上安装它时,我看不到打开它的选项。应用程序安装正确,我甚至可以在设置中找到它->应用程序。。。

    文件夹结构

    app/java/com.example/work/MainActivity.java

    app/res/layout/activity_main.xml

    app/manifest/AndroidManifest.xml

    你能帮我修一下吗?我从来没有用安卓工作室制作过应用程序,所以一切对我来说都是新的吗?我将非常感谢。

    1 回复  |  直到 1 年前
        1
  •  2
  •   CommonsWare    1 年前

    你错过了 <activity> 元素,该元素告诉Android您的活动,并且您希望它出现在启动器中。

    将您的舱单修改为:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.Work"
            tools:targetApi="31">
    
    
            <activity
              android:name=".MainActivity"
              android:exported="true">
              <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
              </intent-filter>
            </activity>
    
    
        </application>
    </manifest>
    
    

    以下是我一本旧书的节选, Elements of Android Jetpack :


    的孩子们 <application> 主要代表的“目录” 应用程序。

    Android有四种主要类型的“组件”:

    • 活动,表示UI

    • 服务,表示与UI解耦的后台处理

    • 内容提供商,将数据库或数据流暴露给其他应用程序或 操作系统

    • 广播接收器,提供发布/订阅的“订阅者”端 应用程序和操作系统用于通信的消息系统

    其中大部分将通过相应的子元素在清单中注册 属于 <应用程序> :

    组成部分 要素
    活动 <活动>
    服务 <service>
    内容提供商 <provider>
    广播接收机 <receiver>

    你的应用程序可能有几种类型,例如有几种活动。你的 应用程序可能没有特定类型,例如没有广播接收器 已在清单中注册。

    ...

    <活动> 元素具有 android:name 属性这将识别 包含活动实现的Java或Kotlin类。 这个 android:名称 在本例中,属性有一个前缀为的纯Java类名 一个点 ( .MainActivity ). 有时,你会看到 android:名称 有一个完全合格的 类名(例如。, com.commonsware.helloworld.MainActivity ). 有时 您将只看到一个裸露的Java类名(例如。, MainActivity ). 二者都 主要活动 .主要活动 引用将在您的 项目的包——您在中声明的包 package 属性 的 <manifest> 要素

    有时 <活动> 元素将具有 <intent-filter> 描述此活动在何种条件下的子元素 将显示。大多数应用程序将至少有一个 <活动> 元素,将您的活动设置为 出现在启动器中,因此用户可以选择运行它 <意图过滤器> 元素确实如此,但其工作原理的细节尚不清楚 这本书的范围。只要说只要你看到 一 <活动> 具有此特定的元素 <意图过滤器> <action> 属于 android.intent.action.MAIN 和一个 <category> 属于 android.intent.category.LAUNCHER ), 你知道这个活动应该出现在用户的启动器中 能够启动。